terra/0000755000175000017500000000000014203314542011517 5ustar nileshnileshterra/MD50000644000175000017500000004544614203314542012044 0ustar nileshnilesha3adb0c5151061ad7ed9f472b7fbf951 *DESCRIPTION c3c90c8035d0db06e1ee8a0c59aef9df *NAMESPACE d8aabb576acaadb8d799218ae07b0223 *NEWS.md d9fcf73cab2bb1a592da87bca255172b *R/Aclasses.R 938dcf41641889c2c9a28bcdf5ea64dc *R/Agenerics.R 7a239d4a5ec88983f777e556c6c7d8c7 *R/Arith_generics.R b42d3a90700a1d1b89d4560100accffa *R/RGB.R 4eccf01258960c8ca29765bc398f6926 *R/RcppExports.R 8967e825ef6ff3084dd06bb8a4de661a *R/SpatRasterDataset.R 7fb340e8d6f82ca0f4beb95fa82d1561 *R/SpatVectorCollection.R 8cd2fe818d92a33d65f314ef1c539fb2 *R/Zdeprecated.R 456966cd6b738bc291d09f2abe5068b9 *R/aggregate.R 497c56f518af8adab01063de5a62fcb7 *R/animate.R b3ac2da8d2c7218bd46ec4ac5d2eb2d6 *R/app.R 816959a5e0d2c65e65d56d311df599b9 *R/approximate.R 9c0657e683968d2a13a22b2aea6ea900 *R/arith.R e9ed509d18dc3e29c1da8410ce2a0f45 *R/autocor.R 4a1b390d82f95cabbc05571c2f2e0da9 *R/cells.R b55e885f3537c7d5d6aef400c4b7695b *R/clean.R ac199d45a26aeef808dd0414fb9c548c *R/click.R db24e90264162eb0473f7ee1130fd409 *R/coerce.R a120eeb750230e835005eac5693bad81 *R/colors.R 3aca5aa328d445b1d1874e20c951e7c6 *R/connect.R ddeb83e15d2101783d6095c6ca419da4 *R/crosstab.R c7a2c2d1b917159ed20fd1f4b67eb3c8 *R/crs.R 65bad45832cb01fd42e3fa48b6c8f062 *R/dimensions.R 98122abd0ac14d6d7354696b49e61cab *R/distance.R 608ecef210951140b103c50e785d4366 *R/draw.R 7fd085919984c8c6d4543a6d0847602f *R/expand.R 842df630e3b70c820256ede796c06adb *R/extent.R 54142bbb058d2b72421f1269d5df5e89 *R/extract.R bca4d6389e5d10f1f56da3e055061052 *R/focal.R c9f3d25a5df40093a0c5dec62b6f62f7 *R/focalMat.R 364fc64c240991e681e33a83de364611 *R/gcp.R d50212c439ffaadf6544cc6f2e65345d *R/gdal.R 3fd74be425e3aa5e6af307b9b5a59e46 *R/generics.R ed060034e1a6339e8a379641431b87e3 *R/geocolors.R 990fd3a8eb745377ad39ce2a69a07267 *R/geom.R bae31d7d2eddae76d2373ffd42c565aa *R/gridDistance.R 5a98da2941f9858904b3fe29269d584e *R/hist.R 7b1223c29aa48dd6d6f5ae91a105dc8d *R/ifelse.R d8024447a75d86b799aa58109b12e91f *R/image.R 8a0896cb0fa648ac21f9a7fe93acc199 *R/init.R 6ac760abdca1eda3c5b850d642214794 *R/inset.R 78f2be2f243a7560cbdcbd3b0324f01b *R/interpolate.R 3e263fa51ab030d6baaa799d4a08e1bd *R/lapp.R 3a814c4318ec4b4a50a978ee654b8eba *R/layerCor.R dfd3a2ac7e7a85d339d0354425d53a73 *R/levels.R cc1062c1989bdacb26682b8d90e5982f *R/lines.R 061ef95c63a4b84aff0d42d192ccfe41 *R/makeVRT.R 7fc5a3b221c9b66bd5375e9e5bd14b61 *R/match.R bd80cf597abe04a2f993b4c83d38236e *R/math.R bd49d342df3efc71b7bcedea0fc18eec *R/merge.R 06542c408746d93910361dbe9003f345 *R/mergeTime.R 1f132c794c28c9ee061685093a528cc4 *R/messages.R f95228190decb39e853442938f9fb7e4 *R/names.R ffc0d2938e5fd567a9ed97a2972f96dc *R/ncdf.R 9a48bb6ba198bb07ab4e83f07effd6ce *R/options.R a82a8746a9c03d59b00c954907cb95cc *R/pack.R 6c96d5b0396cfb08a9f5b972ff8a5d5b *R/plot.R 056aea695726bea0f3dbc5f25377f18d *R/plot2rasters.R 0e9084804319dcab36216b7d20016f30 *R/plotExtent.R 3db285276c95143f1d2649c349fb8eb3 *R/plotRGB.R eb4b3df046ea4bafb927a7f4f60ef105 *R/plot_cartogram.R 002baba628aa6a09c039bb1bed2a2790 *R/plot_legend.R d3be6223a5f4e3ad9ea6702af0609c6b *R/plot_raster.R 6b32c118ecfa47f9b02a3e07b0e2fb02 *R/plot_scale.R ecde26272660d08ab3f753c573a43aea *R/plot_vector.R d41d8cd98f00b204e9800998ecf8427e *R/polygons.R b01a408b022405a7af208cbbebbd90e0 *R/predict.R 282e8d6673ac4b4e154e248b3c845681 *R/rapp.R c21751496e0fdeb36e6215b1d05aaa81 *R/rast.R 30402d0c9baf199f908410f147c9299e *R/rasterize.R 15cbbc158dce5b41cf7906b2b887fd6e *R/read.R df9b737ea72fc3ea89a3acdf4f474109 *R/readsvg.R 8ad9c9865e59ee623bfd75ba6edfa8ed *R/relate.R a3b595cc040180e64b4bfe81aa63dce8 *R/replace.R 4c1ec64a4d6174860ca7ff9c9379d0e4 *R/sample.R 0e2301580e8507832332c2bd14e27741 *R/select.R 0e6f42939e78d755adefba6effc4083f *R/selectHigh.R 820f171fd9476d7cac36a18863492738 *R/show.R e222b88b3b73306e93418385dcf9e7b9 *R/spatDF.R 2861a17dad6fbfcc75f48d6c494d43a4 *R/spatvec.R eadde547f8e4175f2b26dbf09480b25a *R/subset.R e2e1cc93554058c9995b25c837371d3b *R/tapp.R 9c548ea4690de8bcc956d496baaab5ab *R/tempfiles.R b0d328373d0f224931c32b7c919125d0 *R/tiles.R 875f3fc2abc5ff94b682d67aa1cd18bb *R/time.R 90e0c6a777c8a70bfb8e123ba7dc5e23 *R/values.R 67072649ad4aa4194d232d191ae9d57b *R/vect.R 96b55a4b766668a8d10f7a68aa95f337 *R/window.R 741f5ea7e47e78607ad1a223431ee01b *R/write.R 5b74e5bbc165eca0b1567396a9d0dc78 *R/xyRowColCell.R 22ad439e1a8550481bd2082390fa444d *R/zonal.R c3b56a095982381dce7a07cfdf6b037d *R/zoom.R 9a1dfe6128a1946e6d534dea2faef044 *R/zzz.R 0513ced67884bcb39614d15070870521 *cleanup 20835d1679af194e3ceacaa15b24e8b8 *configure c9200e0a2407c973d914931f6b0d8bb6 *configure.ac 9f0ba0023d2db45f72e80f55a14f63cb *inst/ex/countries.rds d069a3466d5ca118b4330b322793b821 *inst/ex/elev.tif ac2a75deea3202ebb856e5aea4dacdae *inst/ex/logo.tif c257dbd91925dd42614dda2cf19a58a3 *inst/ex/lux.dbf c742bee3d4edfc2948a2ad08de1790a5 *inst/ex/lux.prj 4ae2847099f7574e36516738dc411a0f *inst/ex/lux.shp 5d6304a3bc11ffe01ffdda30514d15df *inst/ex/lux.shx 17cef336212cebba7255c8b6192d882f *inst/ex/meuse.rds 90bfad2ac55e1bae8c5e0a7538675ca9 *inst/ex/meuse.tif dc88389d6b233f584a493b654777f14a *inst/tinytest/test_aggregate.R 87d2196301fb59f07d872fa73ebf6015 *inst/tinytest/test_cats.R 1575e0645081e0bab2e93c9906d7377f *inst/tinytest/test_classify.R 0774012abc2fda8ca5d4d91821b7f83c *inst/tinytest/test_crds.R b4dae919e97f8663f49436e4f96e511c *inst/tinytest/test_extent.R 97afe94f04a5140c7510a21c65209194 *inst/tinytest/test_extract.R 4640e1d4c0e852af495ac1a1e0025c29 *inst/tinytest/test_focal.R 3155a6145ed52059b93196ef5e5e554d *inst/tinytest/test_geom.R 4171d6f87648d1db9bdf2db49cc1d1fd *inst/tinytest/test_global.R 292ba4d9fbd81292ffc80d71df16a53f *inst/tinytest/test_matrix-input.R c485a04f17f6ed3599168cc464138165 *inst/tinytest/test_patches.R 9e82a26cbba71c9149ff7759b6292cfc *inst/tinytest/test_raster-vector.R 961502d8b85cc4f42e2c86fb3d3cd361 *inst/tinytest/test_vector-subset.R e1ea9ec84dab6a53f0a6c788230c2451 *inst/tinytest/test_window.R 51186a2c71320948a138528b5945331b *inst/tinytest/tinytest.R 872ef74366712806047c9eab4f00a7d9 *man/NAflag.Rd f7b08c7f8d50b0423650d30b8f7920b4 *man/RGB.Rd 3c771e3b37d0bd47d1f660c72fb8a55a *man/SpatExtent-class.Rd ab4059d955243344c62cf27f5be5d199 *man/SpatRaster-class.Rd a428185816bce636cda3f4c0af9f49b8 *man/SpatVector-class.Rd b9ef19de7aec2f037dcbeb1bf8ad3d41 *man/activeCat.Rd 0624f5586209a34669eed66f0bdda151 *man/add.Rd 564e5fdb6a9816d1a7933040810e88de *man/adjacent.Rd e3fa87be4df1a37ad714658e3911d0d4 *man/aggregate.Rd ea15db746d040ef744b5438c36b9479f *man/align.Rd 9fe981e7d716f8369e554d7cb01d0d09 *man/all.equal.Rd 0ba526f3af62da8981e8d1d5200676dc *man/animate.Rd 173eedd9592e963b4802f0ed7a69f83c *man/app.Rd df57e93115e239ebf3dc90c5e9d17086 *man/approximate.Rd 6a1482262f52219aa0ea50ce166e4477 *man/arith-generic.Rd b701124ed992dda6dbe636ba2e2e6388 *man/as.character.Rd 90158c5ac4c723dd3a312a488ef42441 *man/as.data.frame.Rd 58c7a187c1e9b1637a52130b3bec98d8 *man/as.list.Rd 38ee437104506d597e0c6924779067a6 *man/as.raster.Rd 646475607d1eb3fd1f32603ca9231ab1 *man/as.spatvector.Rd be09e111035393260531ecc451fd6fff *man/atan2.Rd 9b49dfe86634b77cf89c1bffe25f3d2b *man/autocor.Rd 813b72b519f986976fb9dcc2cbe0d9c0 *man/barplot.Rd 81a4d07dad35d8b306e83639c167bca0 *man/boundaries.Rd a2101bac546decea00a3dfcfa2b0d3ff *man/boxplot.Rd 640bbd1d6c4b27a4177523acf2c05d54 *man/buffer.Rd c0fb4bd46ad5e7f78db5463fba745d4e *man/c.Rd d8d44b6ee3ce7552e21c2c9cbe81da6b *man/cartogram.Rd 04f3a6660f8a7d4ffeceb7563f0586ea *man/catalyze.Rd 2c45073e96ebfc871e61d4909bd15d4f *man/cellSize.Rd 5f3202de295e2c0597d20f442f1979d9 *man/cells.Rd 5256a5212dbe1badea2370dbef43e435 *man/centroids.Rd 836f45eee9f13383d4be9a8826ea798b *man/clamp.Rd 5cfc0cecd4e5fa21e5250e298c8709f6 *man/classify.Rd 345515d19b08fbf75bb6b256e267e5e6 *man/click.Rd 38dd1b96eb52773f3c065eccf776205b *man/coerce.Rd cf086689f3a1d8f8f126bc4af9015ff2 *man/collapse.Rd fd57ae669bcd9bec6823a91112c67720 *man/colors.Rd e5784bc137993694686809f429b531ea *man/compare-generics.Rd 7cab78394fbc1a53560db36873174464 *man/compareGeom.Rd b6f2cdd1e6e32ec546d4674ec4055d03 *man/contour.Rd 9cd13adbc626d8aad360b13a4c183b07 *man/convhull.Rd 444ff1b3d45f74d3773579b32b7e412a *man/coords.Rd 1293d696621b9cbed1b5d489cd28541f *man/cover.Rd c3fa2db4cf948ef4be7179c92993f06e *man/crop.Rd 14d34d50d0b931e8376527cc6734e18a *man/crosstab.Rd ca668042853c662c28823ed9586eede8 *man/crs.Rd 2a82a40e7a8b7e19d7283399b0358159 *man/deepcopy.Rd b0e56ee0cf68ffd2c029d052882815d1 *man/densify.Rd 49a8f4f5a263791ab3ac2867182e453f *man/density.Rd a92e15edc79f41a0bb9509611986658c *man/depth.Rd a33dfa0fd979bb08c8fac0784a8cd0bd *man/describe.Rd e661a4248cf02e43d46f11ea8ed66aa7 *man/diff.Rd fe39f84a71093396b1fe696ba5dc4652 *man/dimensions.Rd 20d39baa1cf2a1f0578de2c4ff296cd2 *man/direction.Rd 5c4464ede26e7b7ca8b49519b5645b74 *man/disaggregate.Rd fc5c372cb1d234c34934338cd5a6bbeb *man/distance.Rd ebedcc226f1185fd5cd55417d96b7b60 *man/dots.Rd 30016744c0c24077a17eb98215bfaddf *man/draw.Rd 1a349332b9184f1f1546094f3213aa18 *man/erase.Rd 1154d074c1685c708c2dff15ec5c1996 *man/expanse.Rd 06a3dc4241f7e9f4d4eca2e07aff5672 *man/ext.Rd 3af8570a7a28c62416f565b113867d14 *man/extend.Rd 7abb46f46979b2d33ee6b112e2bc75bf *man/extract.Rd 10780cf1475b4b49d7f76dac686b4138 *man/factors.Rd 97d6828fc02dbd2cf107273bc05defa5 *man/figures/logo.png 50a08c42736e798ddbae8f4761122b21 *man/fill.Rd 2962f0e9f41a61692f6e7387415f423b *man/fillTime.Rd 9f76cf4c5485f9128480537ae409a9dc *man/flip.Rd 1d6e618164f1ccc76fa41f53538800e6 *man/focal.Rd d83b87fed8c2c3d70bee55b0c4676006 *man/focal3D.Rd 41a7adfd3407cfb88d106bb36a9a2d95 *man/focalCor.Rd 96786183e042ff9e26ad3159a272710a *man/focalCpp.Rd ba564ff57f130af0fc70f8d0bf8377e7 *man/focalMat.Rd 98ec4454e15ce1227ec5df57f019decd *man/focalReg.Rd 13b056054c3fd833c1095d3c1d1985fa *man/focalValues.Rd 4cf47539222eed060e47d21b4060ba49 *man/freq.Rd 0cdc4dd44b4939c17da3d780d637f7ac *man/gaps.Rd f9331066e5bb1c49b7501250792e85a9 *man/gdal.Rd d93f42114931b73c4fcd12c82a1758b1 *man/geometry.Rd 0d1ee1289ea7cdae3d755c4600f0bad3 *man/geomtype.Rd 58d50226d45b575323c37e2430f44c95 *man/global.Rd 180ca53e75cb7d70f8a9f4633eefa520 *man/gridDistance.Rd 5d619e916009630a303caf68ab87746e *man/headtail.Rd e5ef2a314e9c8e436cadc01ff0f54f64 *man/hist.Rd 1a298c58baaccd0405dceca4e6179eeb *man/ifelse.Rd d5eefbc0f0588366e31c040d0e90f4aa *man/image.Rd 7dcb850b3c680ac145431aef62253882 *man/impose.Rd 8d67a881c1939ad374ed227e883421a6 *man/init.Rd 4c3b56633d052654b02949619c3f7042 *man/inplace.Rd 0203ea0e9f978adca3cf7f55d2f92c40 *man/inset.Rd 5d44b8408ce99d19b04181b78dca745f *man/interpolate.Rd f7000f5d120869e3c766ea366e66020e *man/intersect.Rd f5ede5a56d19af68301d0992643a45a9 *man/is.bool.Rd efc1ebbca5200d01a0cd3ed647754726 *man/is.lonlat.Rd 868a820c9391364d144a323b2f5c2476 *man/isvalid.Rd 8530ac2e65c1118e840ba5dfd1270c19 *man/lapp.Rd 4c961e887fb13d7191c1d602a4c04813 *man/layerCor.Rd 14db525c3bc3047cfb9d1678d83b3390 *man/linearUnits.Rd 9e90c73b2f61ae85d3a290cdfccd3c31 *man/lines.Rd f76d02711bab12166048e27e7f3828b4 *man/makeTiles.Rd b6def9304dede9d2f1b93877138b9580 *man/makeVRT.Rd 4bcaf252bebb586666ac3d923bf434a6 *man/mask.Rd a180a0bec9a9fb2ff1b288a597eab21b *man/match.Rd b57aa00c271c6c306f89fe0537bccdc7 *man/math-generics.Rd 65a186f43c942818b72c83f017c6404d *man/mem.Rd d20b22a4556b3344b31fbbefd70d780e *man/merge.Rd ed01e533f4ffb82db6a8004b74214072 *man/mergeTime.Rd 62e4f306d107603c6540831255cd7789 *man/minmax.Rd e63d48d1f97028e898e97901f186294a *man/modal.Rd 933afba728a6ce7bdfdafc2870d318d3 *man/mosaic.Rd fe1353f453bd8041efef670fe4b8e9e2 *man/na.omit.Rd 03e75214c1d3db8167cb2d994abd626e *man/names.Rd 7fa64f88ef426d21e99235279f8b8d5b *man/nearby.Rd 4987564055c0746a4f1df7b17dc10380 *man/north.Rd 65962f36dc0517a5aa550967f2dc4b9f *man/origin.Rd c661c4e795e0a7036a14358ef58aa46c *man/pairs.Rd 9dbd2e3fa2dcb96fc9cad20c584e19de *man/patches.Rd 5eddc1343a819e9aef1b8334135663f4 *man/perim.Rd 7a7ad0b1333f3b202000c73713f72e15 *man/persp.Rd 47ce7237b0fbea6e51c0782f89320034 *man/plot.Rd 9ec2dd8e7ddb4e34901c8d735e8714c6 *man/plotRGB.Rd 6d1b6a232c5c28d0a4a8fd2d887ac6ba *man/predict.Rd 913b2f33b75440998f9b435dfafded9f *man/project.Rd c10ad11e804a818fca84fb43c6d62a7b *man/quantile.Rd 0363d6b69fe7af61d0b683d3ea14fb5b *man/query.Rd 6171f06692e69f9841823cf19714f89f *man/rapp.Rd 88ab8d7a737849cb8c98624e0e2c8474 *man/rast.Rd 6f64a6f42ea5731d69f005cabf4ba8ea *man/rasterize.Rd b71a29fee43780c7ea062a288b3aaee4 *man/readwrite.Rd aebee1d2843c8013a2f5e6aed3b22e07 *man/rectify.Rd 9a46695850bbb262f0a7e79368bcd5e0 *man/relate.Rd 8bf3441bb795c39a1d25f27ca790a08a *man/rep.Rd ff06e38e966680639a5b0b997ee0bd73 *man/replace-vector.Rd 4747a651e7c1497e80db14118247bf02 *man/replace.Rd 5e671b76a285a3f366e4179b12e1511b *man/resample.Rd 76b69f0cfd42902b9c16abc5586c4bbc *man/rescale.Rd 29bd11b3ba1d83091ad71a70d0d2d80c *man/rotate.Rd 7eec73a26a56ff7d19a7e0fee7bcf40d *man/sample.Rd 6955e00e5565cd28099ddbdaf72b7900 *man/sapp.Rd b79a4b053f84c4496874b4bf31fb34a8 *man/sbar.Rd 6ca7b94176237e3729c41237511de5cc *man/scale.Rd 4d6bcfdb14cfda155ffeb9f307495d38 *man/scatter.Rd 28d4c23424366c4d4be2358336b449e7 *man/sds.Rd 8f6955c928c95540aaa0ee6cb2d68f2d *man/segregate.Rd 10937da7c02511e8a0105d1264a66d21 *man/select.Rd 9340d9fa7b5d4fbf540ab3573eb59511 *man/selectHigh.Rd 295d389078be60314f261c9136b5a276 *man/selectRange.Rd 6dcaedb2ec54d7bf12099dbd8e1b788b *man/setValues.Rd c7f1eb8d209e9c5f08db272a61c3d0e7 *man/shade.Rd e6ee3f8e0de492704b6ef0b7b881d66c *man/sharedPaths.Rd 987a3ee4f5202801804e4d598f22dc47 *man/shift.Rd e25b85d4b30927273050105b06a6249f *man/simplify.Rd ea909b2b957793632cc214a69f931df0 *man/sources.Rd 8a202689618988df693cb90d7be2d3ce *man/spin.Rd c731caadddb604a9fb5ca654cc6f88da *man/split.Rd adc1cd5c1d43b157ac265f5121317f99 *man/src.Rd e221cc70f8dd133c7b9724d164fbd594 *man/stretch.Rd 905b879e51dd2a9acfd6764982d5aeb2 *man/subset-vector.Rd a95fda8b0d82a0615f86554240d9e456 *man/subset.Rd 0a8d3c147b592fbfde81f1eb4fbc9216 *man/subst.Rd 38d2b70518ace6d7525065caeca043e3 *man/summarize-generics.Rd f10f6268af3cc89acbf66969b0c977a1 *man/summary.Rd 37c0fa6840edb59c613ab2c575a436c4 *man/svc.Rd eb16f9e737584eb2211bff067bab2f21 *man/symdif.Rd c55f5f2e9135e39388a5e79c2e3c1323 *man/tapp.Rd e970570715f6b97b6e7ecfb1732df24a *man/terra-package.Rd 3726c3390fee64f0686ffa777affbf86 *man/terraOptions.Rd 33689238fa83caa3e012d8fa3e8c5f3f *man/terrain.Rd 9cf3c77018e58237e3214760781ca1c8 *man/text.Rd e638174a0c62d66bdd7a96cc80225e60 *man/time.Rd f631416068cdb1f682c77127c1a97258 *man/tmpFile.Rd 9e61b2630de00c32fcf0d3833ea74453 *man/topology.Rd c1294594b9ca56ffd88909f32ffe6f47 *man/transpose.Rd 80be00178c45e9acc17d639d4db9f17b *man/trim.Rd 2fe5f91f4533bcd710daf1e51978b035 *man/union.Rd da8e7ece9aebac344e1fb86cc31413ef *man/unique.Rd 0bc2b2ea6154dbe2e897953dcf132c3d *man/units.Rd 026fc84d9d573162e6a4f9b96255cc11 *man/values.Rd 3c1cb407e2513ba53b0b511f8e3ae0b9 *man/vect.Rd 312a18be8474958ffb2de921a6fd2d55 *man/vector_layers.Rd de6d0830de8d279763ac4ddf74088fd6 *man/voronoi.Rd 48e8ab54f6d43b65e3132bb603dc30b5 *man/vrt.Rd ab2877422982b3f680f40f29113ce7ad *man/weighted.mean.Rd f964592e06ae307bad37c429341c4922 *man/which.Rd 5badfd6448dfe36542e2b89716ec4444 *man/width.Rd 1aff175a1d2e862f77fd4dde1927addf *man/window.Rd 27fc32028df35df04fb083e8ebe35c28 *man/wrap.Rd 5461c091ba96e42242dedd8946a851e8 *man/writeCDF.Rd 081e4cb5960ed3cbcc37a82ffdc07e41 *man/writeRaster.Rd 95a4a9c866d960d4eaea1d969fb8e8ad *man/writeVector.Rd c3a31fd636efec517ba040e4e845d798 *man/xmin.Rd 3b42cc002714e4b202748cb635ec2acf *man/xyCellFrom.Rd b66a39f9211b2edb1afeaf4e93135852 *man/zonal.Rd 5dfd7a32fe79653b9d2fdcf6a5963738 *man/zoom.Rd adc2fba1a7a36b617329645392cf6777 *src/Makevars.in 4dba07857f5871e42232f88f4caa1d53 *src/Makevars.ucrt d379d5724a820784efcbe0b715eea380 *src/Makevars.win 37ee144abeb36df9affb194cf3859d4c *src/NA.h 72424b77a47059e4578627f43fee6f6e *src/RcppExports.cpp c290dcabbe559ae4d9a832eed641de39 *src/RcppFunctions.cpp d47bfc290737e1bb166238b758965c7c *src/RcppModule.cpp 8466f0093d6b34b7427f9220d2e02395 *src/arith.cpp 151739852c286ee46e0fc89b6c9e6fb4 *src/crs.cpp c9cee35b652c280a535bcdf8b463d08e *src/crs.h 2ba38901f5bd4f7ea619d18c6be94c8f *src/date.h 3e96624539a1e438f35bf36cf4de3a70 *src/distRaster.cpp e201e16c5c4976cf02fcd3f9bec1da73 *src/distance.cpp a582f232c03a1b88e194686a6ba8fac8 *src/distance.h 8b4e2f113d5ddc159772ee58bc18ba3f *src/extract.cpp 6c166ea29951bc5ad3326782d51f149b *src/file_utils.cpp 7850c361cdc96f93e35065b5e143ea2a *src/file_utils.h 0cafec20bf365268f55c2fae217063a3 *src/focal.cpp 4565c1c11ca6e083210c151e5c15c769 *src/gcp.cpp a2160c375076c1620a82ac4df3eb2c48 *src/gdal_algs.cpp 965e010170518d910f30fb6e8288397f *src/gdal_multidimensional.cpp 847417175670894b2d026c415f079be2 *src/gdalio.cpp 1ae564db9a722f8faa74ca5459e1feca *src/gdalio.h 4f277083c49bd086621abc203160e993 *src/geodesic.c 598c2f9f280f518436b2f8876df17a81 *src/geodesic.h feab492237ac4058acc040f70c797feb *src/geos_methods.cpp 9ddbcf7d751231a90992210beca3441f *src/geos_spat.h 64249abee1928f486b85e3c9a73c2791 *src/geosphere.cpp 83cdc856c845c93180734521a36540fa *src/graticule.cpp 41db230984b49ac6460885379a0d5d80 *src/math_utils.cpp 7f7ec0428a20d59498ad1c453d670ee7 *src/math_utils.h 5a68247cbf1fbb4e906f4499896ae9a5 *src/mediancut.cpp 5388a50b53850ced361e690c9d92a7db *src/memory.cpp 27d8bbed9139217818ce878ff0271372 *src/ncdf.cpp 0b78ae969313c4e51685d7f33e4274ee *src/progress.hpp d901380ced3b5323a9761820bdd594e7 *src/progress_bar.hpp 7f9d2cc19f0f7bdf382b94a27a34c153 *src/progress_bar_simple.hpp d6526b9eb1fa635823a1149edf9cc7ee *src/progress_interrupts.hpp 627588eecc34a2fdc80774aefac5ac24 *src/progress_monitor_interruptable.hpp c19572d8fc1a929ac0855870dcf17a4b *src/ram.cpp 8c9da6e32cc8145423a65c80eab2500e *src/ram.h c95da3d98d2b2c2026e67eb508e134b8 *src/raster_methods.cpp f08e5f745934bcff75f203889391351c *src/raster_stats.cpp 798aa819a916336828168974114a360a *src/rasterize.cpp 18aaf787cc2812895d6f24696a00bbc9 *src/read.cpp 4137cd54c350d6f06c93f70c7f83a782 *src/read_gdal.cpp 3158ee185006d7e6545cbfb07aa60625 *src/read_ogr.cpp 6fe118e2f168728a5b8ad00b6be2b63c *src/recycle.h 2dc2433aa2d4df60d77dd2a0f2853b43 *src/sample.cpp 24863d6eb4db4295f6b10c133caf96a8 *src/spatBase.cpp 12cd8da1d92e581cc49b7efc15ea6aa5 *src/spatBase.h 9a630c95e3a93326d4a92b7eeaaa2751 *src/spatDataframe.cpp cfd32e7bce506749dbf9889cf35a4b4f *src/spatDataframe.h b01706ea37a5045ea64048d291a41d15 *src/spatFactor.h 18ba292b4ce0599b3b63d09083922fc0 *src/spatRaster.cpp e5089aaf193d1148854b5307435613dd *src/spatRaster.h 47d2241a1e862b40ab67c26d1ec9d961 *src/spatRasterMultiple.h cd942463c4972d0093a45abeb26affcf *src/spatSources.cpp 2f8315878db3602e1a07870c9bffebe5 *src/spatTime.cpp 6159abe24a424bb6efde6d2e0b94d031 *src/spatTime.h 06de0b90f00fde0e5eb26e24c7058d52 *src/spatVector.cpp fbdd4c954a539a8aee184779cbf80afd *src/spatVector.h d48b2f083a8157ae487b1f95bc295731 *src/string_utils.cpp 6b96fd732320ea72f098684d21f521d1 *src/string_utils.h b6fdb7f34267ec750c483f490e6efa6a *src/vecmath.cpp 1aaf5fcf2368990819effb2bff8b1037 *src/vecmath.h 8d9dc49ce421275a290ead75d79c084a *src/vector_methods.cpp e0593d009e5a13288193f33911eab26f *src/write.cpp ebc61fce918c00c1adc35697d25d9428 *src/write_gdal.cpp 96f314db8587ff1c4255b38af10f1e8d *src/write_ogr.cpp 51186a2c71320948a138528b5945331b *tests/tinytest.R 81bb75eaec3d6d63ff9b612e30384c3c *tools/winlibs.R terra/NEWS.md0000644000175000017500000007547214202771564012646 0ustar nileshnilesh# version 1.5-21 ## bug fixes - `writeVector` and `vect` now work with GPGK if the path has non-ascii characters [#518](https://github.com/rspatial/terra/issues/518) - The results of `predict` with `cores > 1` and more than one output variable were garbled - `zonal` dropped category names when using an external (R) function [#527](https://github.com/rspatial/terra/issues/527) by Jakub Nowosad - focal/focalCpp showed strange patterns when the window size was larger than the block size [#519](https://github.com/rspatial/terra/issues/519) by Alex Ilich - using `xy=TRUE` in `as.data.frame` normalized the names [#538](https://github.com/rspatial/terra/issues/538) by Kodi Arfer ## enhancements - `makeTiles` has new arguments `extend` and `na.rm` [#520](https://github.com/rspatial/terra/issues/520) by by L. Dalby - `project` now uses nearest neighbor as default method for RGB rasters # version 1.5-17 Released on 2022-01-30 ## bug fixes - `app` ignored the filename. [#498](https://github.com/rspatial/terra/issues/498) by jszhao - `vect` failed silently if xy coordinates were integers [#496](https://github.com/rspatial/terra/issues/496) by Márcia Barbosa - The output of `aggregate` was malformed when `nrow(x) %% fact != 0`. [#492](https://github.com/rspatial/terra/issues/492) by Jean-François Bourdon - Integer `NA`s in SpatVector attributes where only recognized on Windows [#491](https://github.com/rspatial/terra/issues/491) by Márcia Barbosa - `plot` failed when using a character variable with many unique values. [#489](https://github.com/rspatial/terra/issues/489) by Márcia Barbosa - `rotate` failed on large files. Reported by Ujjawal Singh - writing raster files with a color table could lead to a crash [#501](https://github.com/rspatial/terra/issues/501) by Kodi Arfer - `crds` replicated the coordinates [#504](https://github.com/rspatial/terra/issues/504) by Murray Efford - `as.data.frame` returned integers if the file stored values as integers, even if there was a scale/offset that creates decimal numbers [#509](https://github.com/rspatial/terra/issues/509) by Kodi Arfer - `project` opened the input raster file in read/write mode intead of read mode. That did not work with files that cannot be updated. ## enhancements - `distance`, `gridDistance`, `direction` and `patches` now process all layers of the input SpatRaster. [#503](https://github.com/rspatial/terra/issues/503) by Chris Haak - consistent copy-on-modify behavior in `()<-` methods. in-place updating available with `set.` methods such as `set.names` and `set.values`. [#493](https://github.com/rspatial/terra/issues/493) by Jean Romain and [511](https://github.com/rspatial/terra/issues/511) by Bryan Fuentes - much faster writing of GPGK vector data by using a single transaction (following sf) [#460](https://github.com/rspatial/terra/issues/489) by Krzysztof Dyba - `aggregate` now accepts functions that return more than one value per aggregated cell - `writeVector` has new argument `insert` to add a layer to an existing file (e.g. GPKG). ## new - new option `method="weights"` for `spatSample` - new `mask` method to select intersecting geometries - new method `is.related` - `values` has new option `na.rm=TRUE`. [#490](https://github.com/rspatial/terra/issues/490) by Henk Harmsen - new class `SpatVectorProxy` to provide access to large vector databases that cannot or should not be read into memory in its entirety. - new argument `proxy=FALSE` to `vect` to create a SpatVectorProxy object - new method `query` to extract parts of a SpatVectorProxy - new method `vector_layers` that returns, and can delete, vector format layers from a database/file such as GPKG ## name changes To avoid name clashes with tidyverse - arrow -> north - src -> sprc - simplify -> simplifyGeom For consistency - setCats -> set.cats # version 1.5-12 Released on 2022-01-13 ## bug fixes - `setValues` and `init` failed (or even crashed R) when using a single value on a largish raster. [#414](https://github.com/rspatial/terra/issues/414) - conversion from `sfc` to `SpatVector` lost the crs. [#415](https://github.com/rspatial/terra/issues/415) by Jean-Luc Dupouey - `buffer` on a SpatRaster with no values caused a crash [#416](https://github.com/rspatial/terra/issues/416) by Sebastian Brinkmann - `writeVector` now assumes "traditional GIS order" (long/lat) if the CRS specifies lat/long. [#333]( https://github.com/rspatial/terra/issues/333) by Agustin Lobo - argument `main` was ignored in `density` when using a single layer SpatRaster [#424](https://github.com/rspatial/terra/issues/424) by dvictori - Summary type math functions such as `min` and `mean`, when used with multiple SpatRasters and numbers, ignored additional SpatRasters [#426](https://github.com/rspatial/terra/issues/426) by Zhuonan Wang - names are now conserved when creating a SpatRaster from a RasterStack that points to file(s) [#430](https://github.com/rspatial/terra/issues/430) by Dan Baston - `classify` with `right=FALSE` ignored `include.lowest=TRUE` [#442](https://github.com/rspatial/terra/issues/442) by Alex Ilich - `patches` now combines patches that connect across the data line [#366](https://github.com/rspatial/terra/issues/366) by Hirscht - `patches(directions=8)` now connects in NE/SW direction [#451](https://github.com/rspatial/terra/issues/451) by Jean-François Bourdon. - `centroids` now considers cases where SpatVector parts are nearest to each other when crossing the date line in stead of the zero-meridian [#366](https://github.com/rspatial/terra/issues/366) by Hirscht - `terrain` created empty (`NA`) rows between chunks used for processing large rasters. [#453](https://github.com/rspatial/terra/issues/452) by Robert Ritson. - `inset` did not draw the "box" correctly. [#457](https://github.com/rspatial/terra/issues/457) by Márcia Barbosa - `as.lines` now works with a points SpatVector [#464](https://github.com/rspatial/terra/issues/464) by Márcia Barbosa ## enhancements - `values(x)<-` now accepts (hex coded) colors as values - `focal` now wraps around the dateline like raster::focal [#242](https://github.com/rspatial/terra/issues/242) by Alexander Marbler - `aggregate` now does not show a progress bar in all cases [#249](https://github.com/rspatial/terra/issues/249) by Lachlan - `as.data.frame or ` are now also implemented as S3 methods to assure correct dispatch by other S3 methods such as `data.table::as.data.table`. See [#284](https://github.com/rspatial/terra/issues/284) by Patrick Schratz - `crs` now shows the correct authority if it is not EPSG. [#419](https://github.com/rspatial/terra/issues/419) by Matthew Williamson - It now possible to add a SpatRaster to an empty SpatRaster (with no values), even if it has a different geometry, ignoring the empty SpatRaster [#421](https://github.com/rspatial/terra/issues/421) by Alex Ilich. - `rast` has a new argument `lyrs` to subset the layers and open the file in one step. - `rast` now has a crs and extent argument. [439](https://github.com/rspatial/terra/issues/439) by RS-eco - `type="xyz"` is now default in `rast` [438](https://github.com/rspatial/terra/issues/438) by RS-eco - `classify` has a new argument `brackets` to show if a side of an interval is open or closed. - further support for categorical data in `freq` and `as.data.frame` [#441](https://github.com/rspatial/terra/issues/441) ngould7 - speed up in processing of multi-layer in memory data [#437](https://github.com/rspatial/terra/issues/437) by Krzysztof Dyba - `vect` and `vect` are now much faster [#413](https://github.com/rspatial/terra/issues/413) by BastienFR - `extract` with points provided as a matrix or cell numbers is not much faster [#341](https://github.com/rspatial/terra/issues/341) - `focal` has a new argument `na.policy` that can be set to one of "all" (default), "only" or "omit". argument `na.only` has been removed, as you can now use `na.policy="only"` - `inset` argument `border` changed to `perimeter` to allow passing `border` on to `plot`. [#456](https://github.com/rspatial/terra/issues/456) by Márcia Barbosa - The compile-time and run-time versions of GEOS are now compared and a warning is given if they are not the same. [#459](https://github.com/rspatial/terra/issues/459) by Edzer Pebesma - it is now possible to add sub-datasets to GPKG and GTiff files. [#300](https://github.com/rspatial/terra/issues/300) by gtitov - general option `memfrac` can now be set to zero (in stead of not lower than 0.1). [#476](https://github.com/rspatial/terra/issues/476) by Matt Strimas-Mackey - new argument `allowGaps` in `patches` to disallow gaps between patch IDs. See [#478](https://github.com/rspatial/terra/issues/478) by Dunbar Carpenter. ## new - timestamps and units are now saved to an auxiliary file (filename.aux.json) for all raster formats except NetCDF when using writeCDF (because in that case they are stored in the netcdf file) - new method `mergeTime` to combine multiple rasters, perhaps partly overlapping in time, into a single time series - new method `fillTime` that can add empty layers in between existing layers to assure that the time step between layers is constant - new method `approximate` to fill in missing values by cell across layers - new methods `is.bool` and `as.bool` for SpatRaster and explicit recognition of Boolean raster data in various places (e.g., extract, plot) - new methods `is.int` and `as.int` for SpatRaster. - when assigning integer values to a SpatRaster, or when reading an integer file, the corresponding layers are now classified as being of integer type [#446](https://github.com/rspatial/terra/issues/446) by L. Dalby - new method `layerCor` (like `raster::layerStats`). [#420](https://github.com/rspatial/terra/issues/420) by Alex Ilich - new method `focalCor` (like `raster::corLocal`). [#427](https://github.com/rspatial/terra/issues/427) by Zhuonan Wang - new method `all.equal` for `SpatRaster`. See [#428](https://github.com/rspatial/terra/issues/428) by Dongdong Kong - new method `math` for `SpatRaster` that implements the Math-generic methods *and* accepts a filename - new method `sds` - new method `rasterize`, see [#413](https://github.com/rspatial/terra/issues/413) by BastienFR - new method `colorize` to transform color representations - new method `arrow` to draw a (North) arrow on a map. [#461](https://github.com/rspatial/terra/issues/461) by Márcia Barbosa - new method `densify` to insert nodes between existing nodes of a line or polygon SpatVector - new method `direction` for SpatRaster. [#462](https://github.com/rspatial/terra/issues/462) by Márcia Barbosa - new method `focal3D` to compute focal values for a three-dimensional (row, column, layer) window - new function `makeVRT` to create a vrt file for a file that needs a header to be read. - new option `method="stratified"` for `spatSample`. [#470](https://github.com/rspatial/terra/issues/470) by Michael Mahoney - new general option `memmax` to cap the amount of RAM that terra can be used in raster processing [#476](https://github.com/rspatial/terra/issues/476) by Matt Strimas-Mackey - new method `gridDistance` to compute distances traversing a raster, perhaps with obstacles. [#477](https://github.com/rspatial/terra/issues/477) by Márcia Barbosa # version 1.4-22 Released on 2021-11-24 ## changes - `focal` now has ellipses (`...`) to allow for providing additional arguments to `fun`. For this reason it does not have a `na.rm` argument anymore as that can be supplied via the ellipses. In practice this means that the default will be `na.rm=FALSE` for the standard functions such as `mean` and `sum`. ## bug fixes - `app` grossly overestimated RAM needed, slowing it down. Reported by Jerry Nelson - `terra` now installs, again, with older versions of GEOS [#406](https://github.com/rspatial/terra/pull/406) by fparyani - `terra` did not install with Clang on CRAN/OSX due to using C++13 idiom. ## enhancements - `lapp` and `tapp` now have a `cores` argument (as do `app` and `predict`). Suggested by Dongdong Kong [#365](https://github.com/rspatial/terra/pull/365) - `focal` now also works with a function that returns multiple values (see [#318](https://github.com/rspatial/terra/pull/318) by Alex Ilich). - `focal` can now process multiple layers in one step. - expanded support for conversion from `stars` objects [#220](https://github.com/rspatial/terra/issues/220) by Jakub Nowosad ## new - `focalCpp` takes a C++ function that iterates over cells to speed up computation by avoiding `apply` (see [#318](https://github.com/rspatial/terra/pull/318) by Alex Ilich). - `focalReg` for focal OLS regression models between layers # version 1.4-20 Released on 2021-11-16 ## bug fixes - `terra` did not install with versions of GDAL below 3 [#402](https://github.com/rspatial/terra/issues/402) by Alex Ilich. - `distance` between two SpatVectors or matrices with `pairwise=FALSE` returned a matrix that was filled by column instead of by row [#403](https://github.com/rspatial/terra/issues/403) by Paul Smith # version 1.4-19 Released on 2021-11-15 ## bug fixes - `rast` with some NetCDF files failed because of bad parsing of dates. [#361](https://github.com/rspatial/terra/pull/361) by Juan Carlos Zamora-Pereira - `distance` with lon/lat data was not correct. [#368](https://github.com/rspatial/terra/pull/368) by Greg Schmidt - `as.polygons` failed with a SpatRaster and a categorical layer that is not the first layer. [#370](https://github.com/rspatial/terra/pull/370) by Patrick Schratz - The filename argument in `rasterize` was not ignored, also causing errors when writing to temporary files. [#377](https://github.com/rspatial/terra/pull/377) by Robbie Price - `rast` crashed if the sds was an empty character string. [#381](https://github.com/rspatial/terra/pull/381) by Dan Baston - `plot` now responds to the `range` argument [#385](https://github.com/rspatial/terra/issues/385) by Márcia Barbosa - `zonal` failed for user-defined functions. [#393](https://github.com/rspatial/terra/issues/393) by mqueinnec ## new - new method `selectHighest` to select n cell values with the highest or lowest values. - new method `vect` to append SpatVectors (faster than `do.call(rbind, x)`) - new argument `align=FALSE` to `project` to align to the template SpatRaster but ignore the resolution - new method `gdalCache` to set the GDAL cache size, contributed by Dan Baston [#387](https://github.com/rspatial/terra/pull/387) - new method `fileBlocksize` - new argument `options` to `writeVector` to pass layer creation options to GDAL - new SpatVector topology methods `mergeLines`, `snap`, `makeNodes`, `removeDupNodes`, `gaps`, `simplify` - new SpatVector characterization methods `width` and `clearance` ## enhancements - `terra` now installs with older versions of GEOS [#363](https://github.com/rspatial/terra/pull/363) - `terra` now installs on CentOS 7 with GDAL 2.1.4 and a C++ compiler that does not support std::regexp. [#384](https://github.com/rspatial/terra/issues/384) by Ariel Paulson # version 1.4-11 Released on 2021-10-11 ## enhancements - the definition of `setValues` now has two arguments (`x` and `values`), just like `raster` had; to avoid reverse dependency problems with `raster` # version 1.4-9 Released on 2021-10-07 ## name changes To avoid name conflicts with `sp` (via `raster`) `disaggregate` is now called `disagg` and `bbox,SpatRaster` and `bbox` have been removed (but could be resurrected in `raster` or under another name). ## enhancements - `project` and `resample` now choose the resampling method based on the first layer, using "near" for categorical data. Thanks to Matthew Lewis [#355](https://github.com/rspatial/terra/pull/355) ## bug fixes - `hist` failed with small samples. Issue [#356](https://github.com/rspatial/terra/issues/356) by Martin Queinnec # version 1.4-7 Released on 2021-10-05 ## note `terra` no longer depends on `raster`. To avoid name clashes between these two packages, and to allow replacing methods from `rgeos` and `rgdal` in `raster`, `raster` now depends on `terra` instead. ## enhancements - `freq` has a new argument `usenames`. See issue [#309](https://github.com/rspatial/terra/issues/309) by Bappa Das - `rast` has a new argument `opts` that can be used to pass GDAL open options. See issue [#314](https://github.com/rspatial/terra/issues/314) - `rast` now takes arguments `names` and `vals`. See issue [#323](https://github.com/rspatial/terra/issues/323) by Dongdong Kong - `crs<-` now warns if an unsupported datum is used. See issue [#317](https://github.com/rspatial/terra/issues/317) - `spatSample` now returns factor values if a SpatRaster layer is.factor except when using `as.df=FALSE` - new method `origin<-` to set the origin of a SpatRaster. See issue [#326](https://github.com/rspatial/terra/issues/326) by Jakub Nowosad - `crs` has a new argument `parse`. See [#344](https://github.com/rspatial/terra/issues/344) - `plot` has a new argument `reset=FALSE` that allows resetting the par()$mar parameters after plotting. See issue [#340](https://github.com/rspatial/terra/issues/340) by Derek Friend - `crds` has a new argument `na.rm`. See [#338](https://github.com/rspatial/terra/issues/338) by Kodi Arfer - `show(Spat*)` now prints the name and EPSG code of a crs if available. See [#317](https://github.com/rspatial/terra/issues/317) by Jakub Nowosad ## bug fixes - `plotRGB` failed if there were `NA`s. Issue [#308](https://github.com/rspatial/terra/issues/308) by Jakub Nowosad - `writeVector` crashed R when used with a SpatVector with no geometries. Reported by Timothy White in issue [#319](https://github.com/rspatial/terra/issues/319) - `summary` now returns counts for the classes (instead of a numerical summary of the indices) [#324](https://github.com/rspatial/terra/issues/324) by Jakub Nowosad - `tapp` with a character index now returns a SpatRaster with the correct names [#345](https://github.com/rspatial/terra/issues/345) by Stuart Brown - `rasterize` with a character variable now adds the ID column to the categories [#337](https://github.com/rspatial/terra/issues/337) by Tate Brasel - `cellSize` now masks values in all cases (when requested with `mask=TRUE`). Issue [#339](https://github.com/rspatial/terra/issues/339) by Jean-Luc Dupouey - `buffer` no longer treats lines like polygons [#332](https://github.com/rspatial/terra/issues/332) by Márcia Barbosa - `plot` now passes the layer index to `fun` [#310](https://github.com/rspatial/terra/issues/310) by Ben Tupper - the `to_id` in `nearest` was sometimes wrong. See [#328](https://github.com/rspatial/terra/issues/328) by Shawn Ligocki - better support for ESRI value attribute tables (VAT). See this [SO question]( https://stackoverflow.com/q/69385928/635245) - `focal` did not reset initial values for NA cells when processing chunks. [#312](https://github.com/rspatial/terra/issues/312) by Jeffrey Evans - `focal` could run out of memory when using a large window and user-defined function, and was inexact at the chunk boundary [#347](https://github.com/rspatial/terra/issues/347) - `zonal` with `as.raster=TRUE` failed for categorical SpatRasters [#348](https://github.com/rspatial/terra/issues/348) by Jakub Nowosad # version 1.3-22 Released on 2021-08-20 ## enhancements - if `time(x) <- d` is set with a `Date` class object, `time(x)` now returns a `Date` object instead of a `POSIXct` object. Issue [#256](https://github.com/rspatial/terra/issues/256) raised by Mauricio Zambrano-Bigiarini - The UTF-8 encoding of character attributes of a SpatVector is now declared such that they display correctly in R. See issue [#258](https://github.com/rspatial/terra/issues/258) by AGeographer. Also implemented for names in both SpatVector and SpatRaster - `rast` method to avoid confusion with the `matrix` and `list` methods in response to a [SO question](https://stackoverflow.com/q/68133958/635245) by Stackbeans - the extreme values used to represent NA where not as intended (one or two lower) for INT2U and INT4U. Reported by Jean-Luc Dupouey on [stackoverflow](https://stackoverflow.com/q/68216362/635245) - `writeCDF` now also writes the time dimensions if there is only one time-step. See this [SO question](https://stackoverflow.com/a/68227180/635245) - `vect` (filename) now has argument `layer` to select a layer from a multi-layer file / database, and arguments `query`, `extent` and `filter` for reading a subset - `subst` can now create multiple output layers See [issue 276](https://github.com/rspatial/terra/issues/276) by Agustin Lobo - `classify` can now create different multiple output layers See [issue 276](https://github.com/rspatial/terra/issues/276) by Agustin Lobo - Argument `alpha` of `plot` can now be a `SpatRaster`. See this [SO question](https://stackoverflow.com/q/68736432/635245) by James McCarthy ## bug fixes - The `filename` and `overwrite` arguments were ignored in `rasterize` - gdal options are now also honored for create-copy drivers [#260](https://github.com/rspatial/terra/issues/260) - buffer for lonlat now works better at the world's "edges" [#261](https://github.com/rspatial/terra/issues/261) - scale/offset were ignored by `project`. Reported by Fabian Fischer - `rasterize` with `inverse=TRUE` crashed the R session. Issue [#264](https://github.com/rspatial/terra/issues/264) by Jean-Luc Dupouey - The output of `merge` and `mosaic` was not correct for large rasters (only the first rows were used). Reported by Zavud Baghirov in [#271](https://github.com/rspatial/terra/issues/271) - `as.points,SpatRaster` did not remove `NA`'s correctly and shifted values. Issues [#269](https://github.com/rspatial/terra/issues/269) and [#273](https://github.com/rspatial/terra/issues/273) by Julian Hagenauer - `rast` rotated values when using an equal-sided matrix [#274](https://github.com/rspatial/terra/issues/274) by Jakub Nowosad - the number of rows and columns were reversed when using `project` with a crs argument. [#283](https://github.com/rspatial/terra/issues/283) by Timothée Giraud - In `classify`, argument `right` had TRUE and FALSE reversed. - `terrain` had edge effects [#303](https://github.com/rspatial/terra/issues/303) by Andrew Gene Brown. - `terrain` can now compute multiple variables at once [#286](https://github.com/rspatial/terra/issues/286) by Žan Kuralt - `wrap` changed factors into numeric [#302](https://github.com/rspatial/terra/issues/302) by Patrick Schratz - `writeVector` failed with "FlatGeobuf" (and probably other formats as well) for not using a proper MultiPolygon [#299](https://github.com/rspatial/terra/issues/299) by L Dalby - regular sampling of polygons with `spatSample` is now much more regular [#289](https://github.com/rspatial/terra/issues/289) by Jakub Nowosad # version 1.3-4 Released on 2021-06-20 ## new - `na.omit` to remove empty geometries and/or attribute records that have an `NA` - new method `src` to create a `SpatRasterCollection` (a loose collection of tiles). - `merge` and `mosaic` now have methods for a `SpatRasterCollection`. To avoid the (inefficient) use of `do.call`. See issue [#210](https://github.com/rspatial/terra/issues/210) by Matthew Talluto. - `activeCat` and `activeCat<-` to get or set the "active" category if there are multiple categories (raster attributes) - `as.numeric` and `catalyze` to transfer categories to numeric cell values - summarize methods such as `range` and `mean` for (the attributes of) a `SpatVector` - new method `shade`, to compute hill shading ## enhancements - additional arguments (such as `na.rm`) are now used by `rasterize` with point geometries. Suggested by Jakub Nowosad [#209](https://github.com/rspatial/terra/issues/209) - improved handling (and documentation) of `gstat` models by `interpolate`. See issue [#208](https://github.com/rspatial/terra/issues/208) by Jakub Nowosad. - new argument `cpkgs` to `predict` to list the packages that need to be exported to the cores if argument `cores` is larger than one. `?predict` now shows different approaches to parallelize `predict` (based on examples in issue [#178]( https://github.com/rspatial/terra/issues/178) raised by by Matthew Coghill). - `freq` now returns labels for categorical layers - `adjacent` now has a `pairs` argument. Requested by Kenneth Blake Vernon in issue [#239](https://github.com/rspatial/terra/issues/239) - `adjacent` now also takes a matrix to specify adjacent cells - `mean` and other summarize methods now take a `filename` argument and disallow non-recognized named arguments. See issue [#238](https://github.com/rspatial/terra/issues/238) by Jessica Nephin - The raster attribute table of ESRI-GRID integer data, or from an ESRI `vat.dbf` file is now ignored if it only has the counts of the values. See issue [#234]( https://github.com/rspatial/terra/issues/234) by Jullee - time attributes are no longer lost when doing raster operations. Suggested by Mauricio Zambrano-Bigiarini in [#246]( https://github.com/rspatial/terra/issues/246) - resample (and project) no longer ignore `gdal=""` write options and use BIGTIFF if necessary (suggested by Ani Ghosh) - new argument `layer` in the `extract-SpatRaster,SpatVector` method to extract values for a single layers specified for each geometry (see this [question](https://gis.stackexchange.com/a/401591/8993)). ## bug fixes - better handling of paths with non-ASCII characters (e.g., Chinese) for GeoTiff but still fails for NetCDF (see issue [#233](https://github.com/rspatial/terra/issues/223) by Dongdong Kong) - `extract` with points and `cells=TRUE` or `xy=TRUE` gave garbled output - `as.character` (called by `wrap`) did not capture the layer names. Reported by Pascal Title [#213](https://github.com/rspatial/terra/issues/213) - `focal` mirrored the weight matrix, thus affecting the results when using an asymmetrical weight matrix. Reported by Sebastiano Trevisani - `terra::terraOptions` now works without attaching the package (issue [#229](https://github.com/rspatial/terra/issues/229) reported by Karl Dunkle Werner) - `app` with `ncores > 0` and a function that returns multiple layers now works (issue [#240](https://github.com/rspatial/terra/issues/240) reported by BastienFR. - `autocor` (local) can now handle `NA` values. Reported by Jakub Nowosad [#245](https://github.com/rspatial/terra/issues/245). - `mask` with a SpatVector and a large (out of memory) multi-layer SpatRaster only worked for the first layer. Reported by Monika Tomaszewska. # version 1.2-10 Released on 2021-05-13 ## new - `as.lines` method for SpatRaster - `as.polygons` method for SpatVector lines - `autocor` has new methods `mean`, to compute the local mean, and `locmor`, for the local Moran's *I* - `sharedPaths` method for SpatVector (lines and polygons) - `RGB2col` method to reduce a three-layer RGB SpatRaster to a single layer SpatRaster with a color-table (with <= 256 colors) - `split` methods for SpatVector and SpatRaster ## enhancements - `rast` now takes the crs from the Raster object, not from the file it may point to. Suggested by Floris Vanderhaeghe [#200](https://github.com/rspatial/terra/issues/200) - `convhull` has a new argument `by=""` to make convex hulls for sub-sets of a SpatVector. - faster processing of large in memory rasters. See issue [#206](https://github.com/rspatial/terra/issues/206) by Krzysztof Dyba. ## bug fixes - `extract` with multiple layers could return a data.frame where the values were not in the correct order (by row instead of by column) - `crop` works again with `sf` objects. Reported by Sebastian Brinkmann [#201](https://github.com/rspatial/terra/issues/201) - `vect` now also works for lines, and should be faster - `vect` crashed R if a file had empty geometries. Reported by consumere [#202](https://github.com/rspatial/terra/issues/202) - `extract(points, bilinear=TRUE, cells=TRUE)` now works. Reported by fab4app [#203](https://github.com/rspatial/terra/issues/203) - `zonal` now works for `min` and `max`. Reported by Jakub Nowosad [#207](https://github.com/rspatial/terra/issues/207) ## name changes To avoid name conflicts with the `spatstat` package - `area,SpatRaster-method(x, sum=FALSE)` -> `cellSize(x)` - `area,SpatRaster/SpatVector-method(x, sum=TRUE)` -> `expanse(x)` - `convexhull` -> `convHull` - `perimeter` -> `perim` - `tiles` -> `makeTiles` - `coords` -> `crds` # version 1.2-5 Released on 2021-04-30 ## new - `trim` has a new argument `value` that allows trimming rows and columns with other values than the default `NA` - `rapp` has a new argument `clamp` that allows clamping start and end values to `1:nlyr(x)`, avoiding that all values are considered `NA` - `spatSample` has new arguments `as.points` and `values`. Getting values, cells and coordinates is no longer mutually exclusive. In response to [#191](https://github.com/rspatial/terra/issues/191). Requested by Agustin Lobo - `area` has a new argument `mask=FALSE` - `classify` can now take a single number to request that many cuts - `mosaic` and `merge` now warn and resample if rasters are not aligned - `extract` has a new argument `exact` to get the fraction covered for each cell ## bug fixes - `flip(x, direction="vertical")` no longer reverses the order of the layers - `extract` did not work for horizontal or vertical lines as their extent was considered invalid. Reported by Monika Tomaszewska - `autocor` did not handle NA values [#192](https://github.com/rspatial/terra/issues/192). Reported by Laurence Hawker - `nearest` now works for angular coordinates - The unit of `slope` in `terrain` was not correct (the tangent was returned instead of the slope) [#196](https://github.com/rspatial/terra/issues/196). Reported by Sven Alder - `quantile` now works for rasters that have cells that are all `NA`. Reported by Jerry Nelson ## name changes To avoid name conflicts with tidyverse with deprecation warning: - separate -> segregate - expand -> extend - near -> nearby - pack -> wrap without deprecation warning: - transpose -> trans - collapse -> tighten - fill -> fillHoles - select -> sel # version 1.1-17 Released on 2021-04-14 ## major changes - `c` now returns a list. `rbind` is used to append SpatVector objects - overhaul of handling of factors. `rats` has been removed, and `levels` and `cats` have changed # version 1.1-4 - No news recorded for this version and earlier versions terra/DESCRIPTION0000644000175000017500000000414414203314542013230 0ustar nileshnileshPackage: terra Type: Package Title: Spatial Data Analysis Version: 1.5-21 Date: 2022-02-15 Depends: R (>= 3.5.0) Suggests: parallel, tinytest, ncdf4, sf (>= 0.9-8), deldir, XML, igraph LinkingTo: Rcpp Imports: methods, Rcpp SystemRequirements: C++11, GDAL (>= 2.2.3), GEOS (>= 3.4.0), PROJ (>= 4.9.3), sqlite3 Encoding: UTF-8 Maintainer: Robert J. Hijmans Description: Methods for spatial data analysis with raster and vector data. Raster methods allow for low-level data manipulation as well as high-level global, local, zonal, and focal computation. The predict and interpolate methods facilitate the use of regression type (interpolation, machine learning) models for spatial prediction, including with satellite remote sensing data. Processing of very large files is supported. See the manual and tutorials on to get started. 'terra' is very similar to the 'raster' package; but 'terra' can do more, is easier to use, and it is faster. License: GPL (>= 3) URL: https://rspatial.org/terra/ BugReports: https://github.com/rspatial/terra/issues/ LazyLoad: yes Authors@R: c( person("Robert J.", "Hijmans", role = c("cre", "aut"), email = "r.hijmans@gmail.com", comment = c(ORCID = "0000-0001-5872-2872")), person("Roger", "Bivand", role = "ctb", comment = c(ORCID = "0000-0003-2392-6140")), person("Jacob", "van Etten", role = "ctb", comment = c(ORCID = "0000-0001-7554-2558")), person("Karl", "Forner", role = "ctb"), person("Jeroen", "Ooms", role = "ctb", comment = c(ORCID = "0000-0002-4035-0289")), person("Edzer", "Pebesma", role = "ctb", comment = c(ORCID = "0000-0001-8049-7069"))) NeedsCompilation: yes Packaged: 2022-02-15 19:39:58 UTC; rhijm Author: Robert J. Hijmans [cre, aut] (), Roger Bivand [ctb] (), Jacob van Etten [ctb] (), Karl Forner [ctb], Jeroen Ooms [ctb] (), Edzer Pebesma [ctb] () Repository: CRAN Date/Publication: 2022-02-17 00:40:02 UTC terra/man/0000755000175000017500000000000014201035750012271 5ustar nileshnileshterra/man/cellSize.Rd0000644000175000017500000000357314201035750014342 0ustar nileshnilesh\name{cellSize} \alias{cellSize} \alias{cellSize,SpatRaster-method} \title{Area covered by each raster cell} \description{ Compute the area covered by individual raster cells. Computing the surface area of raster cells is particularly relevant for longitude/latitude rasters. Note that for both angular (longitude/latitude) and for planar (projected) coordinate reference systems raster cells sizes are generally not constant, unless you are using an equal-area coordinate reference system. For planar CRSs, the area is therefore not computed based on the linear units of the coordinate reference system, but on the *actual* area, correcting for distortion. If you do not want that, you can instead use \code{init(x, prod(res(x)))} } \usage{ \S4method{cellSize}{SpatRaster}(x, mask=TRUE, unit="m", transform=TRUE, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{mask}{logical. If \code{TRUE}, cells that are \code{NA} in \code{x} are also \code{NA} in the output} \item{unit}{character. One of "m", "km", or "ha"} \item{transform}{logical. If \code{TRUE}, planar CRS data are transformed to lon/lat for accuracy} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ numeric. The area of each cell, expressed in square meters, square kilometers, or hectares. } \seealso{\code{\link{expanse}}} \examples{ # SpatRaster r <- rast(nrows=18, ncols=36) v <- 1:ncell(r) v[200:400] <- NA values(r) <- v # size of each raster cell a <- cellSize(r) # illustration of distortion r <- rast(ncols=90, nrows=45, ymin=-80, ymax=80) m <- project(r, "+proj=merc") bad <- init(m, prod(res(m)) / 1000000, names="naive") good <- cellSize(m, unit="km", names="corrected") plot(c(good, bad), nc=1, mar=c(2,2,1,6)) } \keyword{methods} \keyword{spatial} terra/man/as.data.frame.Rd0000644000175000017500000000273114201035747015175 0ustar nileshnilesh\name{as.data.frame} \alias{as.data.frame} \alias{as.data.frame,SpatRaster-method} \alias{as.data.frame,SpatVector-method} \title{SpatRaster or SpatVector to data.frame} \description{ Coerce a SpatRaster or SpatVector to a data.frame } \usage{ \S4method{as.data.frame}{SpatVector}(x, row.names=NULL, optional=FALSE, geom=NULL, ...) \S4method{as.data.frame}{SpatRaster}(x, row.names=NULL, optional=FALSE, xy=FALSE, cells=FALSE, na.rm=TRUE, ...) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{geom}{character or NULL. If not NULL, either "WKT" or "HEX", to get the geometry included in Well-Known-Text or hexadecimal notation. If \code{x} has point geometry, it can also bey "XY" to add the coordinates of each point} \item{xy}{logical. If \code{TRUE}, the coordinates of each raster cell are included} \item{cells}{logical. If \code{TRUE}, the cell numbers of each raster cell are included} \item{na.rm}{logical. If \code{TRUE}, cells that have a NA value in at least one layer are removed} \item{...}{Additional arguments passed to the \code{\link{data.frame}}} \item{row.names}{This argument is ignored} \item{optional}{This argument is ignored} } \seealso{\code{\link{as.list}, \link{as.matrix}}. See \code{\link{geom}} to only extract the geometry of a SpatVector} \value{ data.frame } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) as.data.frame(v) } \keyword{spatial} \keyword{methods} terra/man/boxplot.Rd0000644000175000017500000000272614201035750014256 0ustar nileshnilesh\name{boxplot} \docType{methods} \alias{boxplot} \alias{boxplot,SpatRaster-method} \title{ Box plot of SpatRaster data } \description{ Box plot of layers in a SpatRaster } \usage{ \S4method{boxplot}{SpatRaster}(x, y=NULL, maxcell=100000, ...) } \arguments{ \item{x}{SpatRaster} \item{y}{NULL or a SpatRaster. If \code{x} is a SpatRaster it used to group the values of \code{x} by "zone"} \item{maxcell}{Integer. Number of cells to sample from datasets} \item{...}{additional arguments passed to \code{graphics::\link[graphics]{boxplot}}} } \value{ boxplot returns a list (invisibly) that can be used with \code{\link{bxp}} } \seealso{ \code{\link{pairs}, \link{hist}} } \examples{ r1 <- r2 <- r3 <- rast(ncols=10, nrows=10) set.seed(409) values(r1) <- rnorm(ncell(r1), 100, 40) values(r2) <- rnorm(ncell(r1), 80, 10) values(r3) <- rnorm(ncell(r1), 120, 30) s <- c(r1, r2, r3) names(s) <- c("Apple", "Pear", "Cherry") boxplot(s, notch=TRUE, col=c("red", "blue", "orange"), main="Box plot", ylab="random", las=1) op <- par(no.readonly = TRUE) par(mar=c(4,6,2,2)) boxplot(s, horizontal=TRUE, col="lightskyblue", axes=FALSE) axis(1) axis(2, at=0:3, labels=c("", names(s)), las=1, cex.axis=.9, lty=0) par(op) ## boxplot with 2 layers v <- vect(system.file("ex/lux.shp", package="terra")) r <- rast(system.file("ex/elev.tif", package="terra")) y <- rasterize(v, r, "NAME_2") b <- boxplot(r, y) bxp(b) } \keyword{spatial} terra/man/fillTime.Rd0000644000175000017500000000162214201035750014326 0ustar nileshnilesh\name{fillTime} \docType{methods} \alias{fillTime} \alias{fillTime,SpatRaster-method} \title{ Fill time gaps in a SpatRaster } \description{ Add empty layers in between existing layers such that the time step between each layer is the same. See \code{\link{approximate}} to estimate values for these layer (and other missing values) } \usage{ \S4method{fillTime}{SpatRaster}(x, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{filename}{character. Output filename} \item{...}{list with named options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{ \code{\link{approximate}} } \examples{ r <- rast(system.file("ex/logo.tif", package="terra")) s <- c(r, r) time(s) <- as.Date("2001-01-01") + c(0:2, 5:7) time(s) ss <- fillTime(s) time(ss) a <- approximate(ss) } \keyword{methods} \keyword{spatial} terra/man/colors.Rd0000644000175000017500000000172214201035750014063 0ustar nileshnilesh\name{colors} \docType{methods} \alias{coltab} \alias{coltab,SpatRaster-method} \alias{coltab<-} \alias{coltab<-,SpatRaster-method} \title{Color table} \description{ Get or set color table(s) associated with a SpatRaster. Color tables are used for associating colors with values, for use in mapping (plot). } \usage{ \S4method{coltab}{SpatRaster}(x) \S4method{coltab}{SpatRaster}(x, layer=1)<-value } \arguments{ \item{x}{SpatRaster} \item{layer}{positive integer, the layer number or name} \item{value}{a vector of colors; or a three (red,green,blue) or four (alpha) column data.frame with no more than 256 rows; or NULL to remove the color table} } \value{ data.frame } \examples{ r <- rast(ncols=3, nrows=2, vals=0:5) coltb <- data.frame(t(col2rgb(rainbow(6, end=.9), alpha=TRUE))) coltb plot(r) coltab(r) <- coltb plot(r) tb <- coltab(r) class(tb) dim(tb[[1]]) } \keyword{methods} \keyword{spatial} terra/man/as.list.Rd0000644000175000017500000000210114201035747014135 0ustar nileshnilesh\name{as.list} \alias{as.list} \alias{as.list,SpatRaster-method} \alias{as.list,SpatVector-method} \title{SpatRaster or SpatVector to list} \description{ Coerce a SpatRaster or SpatVector to a list. With a SpatRaster, each layer becomes a list element. With a SpatVector, each variable becomes a list element. } \usage{ \S4method{as.list}{SpatRaster}(x, ...) \S4method{as.list}{SpatVector}(x, geom=NULL, ...) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{geom}{character or NULL. If not NULL, either "WKT" or "HEX", to get the geometry included in Well-Known-Text or hexadecimal notation. If \code{x} has point geometry, it can also bey "XY" to add the coordinates of each point} \item{...}{Additional arguments. These are ignored} } \seealso{see \code{\link{coerce}} for \code{as.data.frame} with a SpatRaster; and \code{\link{geom}} to only extract the geometry of a SpatVector} \value{ list } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) as.list(v) } \keyword{spatial} \keyword{methods} terra/man/setValues.Rd0000644000175000017500000000346314201035750014541 0ustar nileshnilesh\name{setValues} \docType{methods} \alias{values<-} \alias{values<-,SpatRaster,ANY-method} \alias{setValues} \alias{setValues,SpatRaster-method} \alias{setValues,SpatRaster,ANY-method} \alias{values<-,SpatVector,data.frame-method} \alias{values<-,SpatVector,matrix-method} \alias{values<-,SpatVector,ANY-method} \alias{values<-,SpatVector,NULL-method} \alias{setValues,SpatVector-method} \alias{setValues,SpatVector,ANY-method} \title{Set the values of raster cells or of geometry attributes} \description{ Set cell values of a SpatRaster or the attributes of a SpatVector. For large SpatRaster objects use \code{\link{init}} instead to set values. } \usage{ \S4method{values}{SpatRaster,ANY}(x)<-value \S4method{setValues}{SpatRaster,ANY}(x, values, keeptime=TRUE, keepunits=TRUE, props=FALSE) \S4method{values}{SpatVector,ANY}(x)<-value } \arguments{ \item{x}{SpatRaster or SpatVector} \item{value}{For SpatRaster: matrix or numeric, the length must match the total number of cells (ncell(x) * nlyr(x)), or be a single value. For SpatVector: data.frame, matrix, vector, or NULL} \item{values}{Same as for \code{value}} \item{keeptime}{logical. If \code{TRUE} the time stamps are kept} \item{keepunits}{logical. If \code{FALSE} the units are discarded} \item{props}{logical. If \code{TRUE} the properties (categories and color-table) are kept} } \value{ The same object type as \code{x} } \seealso{\code{\link{values}}, \code{\link{init}}} \examples{ f <- system.file("ex/elev.tif", package="terra") r <- rast(f) x <- setValues(r, 1:ncell(r)) x values(x) <- runif(ncell(x)) x head(x) f <- system.file("ex/lux.shp", package="terra") v <- vect(f) values(v) <- data.frame(ID=1:12, name=letters[1:12]) head(v) } \keyword{spatial} \keyword{methods} terra/man/expanse.Rd0000644000175000017500000000375214201035750014232 0ustar nileshnilesh\name{expanse} \alias{expanse} \alias{expanse,SpatRaster-method} \alias{expanse,SpatVector-method} \alias{area} \alias{area,SpatRaster-method} \alias{area,SpatVector-method} \title{Get the expanse (area) of individual polygons or for all (summed) raster cells} \description{ Compute the area covered by polygons or for all raster cells that are not \code{NA}. This method computes areas for longitude/latitude rasters, as the size of the cells is constant in degrees, but not in square meters. But it can also be important if the coordinate reference system is planar, but not equal-area. For vector data, the best way to compute area is to use the longitude/latitude CRS. This is contrary to (erroneous) popular belief that suggest that you should use a planar coordinate reference system. This is done automatically, if \code{transform=TRUE}. } \usage{ \S4method{expanse}{SpatRaster}(x, unit="m", transform=TRUE) \S4method{expanse}{SpatVector}(x, unit="m", transform=TRUE) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{unit}{character. One of "m", "km", or "ha"} \item{transform}{logical. If \code{TRUE}, planar CRS are transformed to lon/lat for accuracy} } \value{ numeric. The total area size of all cells that are not \code{NA}, expressed in square meters, square kilometers, or hectares. } \seealso{ \code{\link{cellSize}} for a the size of individual cells of a raster, that can be summed with \code{\link{global}} or with \code{\link{zonal}} to get the area for different categories. } \examples{ ### SpatRaster r <- rast(nrows=18, ncols=36) v <- 1:ncell(r) v[200:400] <- NA values(r) <- v # summed area in km2 expanse(r, unit="km") r <- rast(ncols=90, nrows=45, ymin=-80, ymax=80) m <- project(r, "+proj=merc") expanse(m, unit="km") expanse(m, unit="km", transform=FALSE) ### SpatVector v <- vect(system.file("ex/lux.shp", package="terra")) a <- expanse(v) a sum(a) } \keyword{methods} \keyword{spatial} terra/man/origin.Rd0000644000175000017500000000131514201035750014047 0ustar nileshnilesh\name{origin} \alias{origin} \alias{origin,SpatRaster-method} \alias{origin<-} \alias{origin<-,SpatRaster-method} \title{Origin} \description{ Get or set the coordinates of the point of origin of a SpatRaster. This is the point closest to (0, 0) that you could get if you moved towards that point in steps of the x and y resolution. } \usage{ \S4method{origin}{SpatRaster}(x) \S4method{origin}{SpatRaster}(x)<-value } \arguments{ \item{x}{SpatRaster} \item{value}{numeric vector of length 1 or 2} } \value{ A vector of two numbers (x and y coordinates) } \examples{ r <- rast(xmin=-0.5, xmax = 9.5, ncols=10) origin(r) origin(r) <- c(0,0) r } \keyword{spatial} terra/man/coerce.Rd0000644000175000017500000000226214201035750014022 0ustar nileshnilesh\name{coerce} \docType{methods} \alias{as.vector} \alias{as.matrix} \alias{as.array} \alias{as.vector,SpatRaster-method} \alias{as.matrix,SpatRaster-method} \alias{as.array,SpatRaster-method} \title{Coercion of a SpatRaster to a vector, matrix or array} \description{ Coercion to other object types } \usage{ \S4method{as.vector}{SpatRaster}(x, mode='any') \S4method{as.matrix}{SpatRaster}(x, ...) \S4method{as.array}{SpatRaster}(x) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{...}{additional argument \code{as.matrix}: \code{wide (logical)}. If \code{FALSE} each layer in the SpatRaster becomes a column in the matrix and each cell in the SpatRaster becomes a row. If \code{TRUE} each row in the SpatRaster becomes a row in the matrix and each column in the SpatRaster becomes a column in the matrix } \item{mode}{this argument is ignored} } \value{ vector, matrix, or array } \seealso{\code{\link{as.data.frame}} and \code{\link{as.polygons}}} \examples{ r <- rast(ncols=2, nrows=2) values(r) <- 1:ncell(r) as.vector(r) as.matrix(r) as.matrix(r, wide=TRUE) as.data.frame(r, xy=TRUE) as.array(r) } \keyword{spatial} terra/man/zoom.Rd0000644000175000017500000000160614201035750013547 0ustar nileshnilesh\name{zoom} \docType{methods} \alias{zoom} \alias{zoom,SpatRaster-method} \alias{zoom,SpatVector-method} \title{Zoom in on a map} \description{ Zoom in on a map (plot) by providing a new extent, by default this is done by clicking twice on the map. } \usage{ \S4method{zoom}{SpatRaster}(x, e=draw(), maxcell=100000, layer=1, new=FALSE, ...) \S4method{zoom}{SpatVector}(x, e=draw(), new=FALSE, ...) } \arguments{ \item{x}{SpatRaster} \item{e}{SpatExtent} \item{maxcell}{positive integer. Maximum number of cells used for the map} \item{layer}{positive integer to select the layer to be used} \item{new}{logical. If \code{TRUE}, the zoomed in map will appear on a new device (window)} \item{...}{additional arguments passed to \code{\link{plot}}} } \value{ SpatExtent (invisibly) } \seealso{ \code{\link{draw}}, \code{\link{plot}}} \keyword{spatial} terra/man/plot.Rd0000644000175000017500000001562614201035750013550 0ustar nileshnilesh\name{plot} \docType{methods} \alias{plot} \alias{plot,SpatRaster,missing-method} \alias{plot,SpatRaster,numeric-method} \alias{plot,SpatRaster,character-method} \alias{plot,SpatVector,missing-method} \alias{plot,SpatVector,numeric-method} \alias{plot,SpatVector,character-method} \alias{plot,SpatVectorProxy,missing-method} \alias{plot,SpatExtent,missing-method} \title{Make a map} \description{ Plot the values of a SpatRaster or SpatVector to make a map. See \code{\link{lines}} to add a SpatVector to an existing map. } \usage{ \S4method{plot}{SpatRaster,numeric}(x, y=1, col, type, mar=NULL, legend=TRUE, axes=TRUE, plg=list(), pax=list(), maxcell=500000, smooth=FALSE, range=NULL, levels=NULL, fun=NULL, colNA=NULL, alpha=NULL, sort=FALSE, grid=FALSE, ext=NULL, reset=FALSE, ...) \S4method{plot}{SpatRaster,missing}(x, y, maxcell=500000, main, mar=NULL, nc, nr, maxnl=16, ...) \S4method{plot}{SpatRaster,character}(x, y, ...) \S4method{plot}{SpatVector,character}(x, y, col, type, mar=NULL, legend=TRUE, add=FALSE, axes=!add, main=y, buffer=TRUE, background=NULL, grid=FALSE, ext=NULL, plg=list(), pax=list(), nr, nc, ...) \S4method{plot}{SpatVector,numeric}(x, y, ...) \S4method{plot}{SpatVector,missing}(x, y, ...) \S4method{plot}{SpatExtent,missing}(x, y, ...) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{y}{missing or positive integer or name indicating the layer(s) to be plotted} \item{col}{character. Colors. The default is \code{rev(grDevices::terrain.colors(50))}} \item{type}{character. Type of map/legend. One of "continuous", "classes", or "interval"} \item{mar}{numeric vector of lenght 4 to set the margins of the plot (to make space for the legend). The default is (3.1, 3.1, 2.1, 7.1) for a single plot with a legend and (3.1, 3.1, 2.1, 2.1) otherwise. Use \code{mar=NA} to not set the margins} \item{legend}{logical or character. If not \code{FALSE} a legend is drawn. The character value can be used to indicate where the legend is to be draw. For example "topright" or "bottomleft". Use \code{plg} for more refined placement (SpatVector data only)} \item{axes}{logical. Draw axes?} \item{buffer}{logical. If \code{TRUE} the plotting area is slightly larger than the extent of \code{x}} \item{background}{background color. Default is no color (white)} \item{plg}{list with parameters for drawing the legend. See the arguments for \code{\link{legend}}} \item{pax}{list with parameters for drawing axes. See the arguments for \code{\link{axis}}} \item{maxcell}{positive integer. Maximum number of cells to use for the plot} \item{smooth}{logical. If \code{TRUE} the cell values are smoothed (for continuous legend)} \item{range}{numeric. minimum and maximum values to be used for the continuous legend } \item{levels}{character. labels to be used for the classes legend } \item{fun}{function to be called after plotting each SpatRaster layer to add something to each map (such as text, legend, lines). For example, with SpatVector \code{v}, you could do \code{fun=function() lines(v)}. The function may have one argument, representing the the layer that is plotted (1 to the number of layers) } \item{colNA}{character. color for the NA values} \item{alpha}{Either a single numeric between 0 and 1 to set the transparency for all colors (0 is transparent, 1 is opaque) or a SpatRaster with values between 0 and 1 to set the transparency by cell. To set the transparency for a given color, set it to the colors directly} \item{sort}{logical. If \code{TRUE} legends with categorical values are sorted} \item{grid}{logical. If \code{TRUE} grid lines are drawn. Their properties such as type and color can be set with the \code{pax} argument} \item{nc}{positive integer. Optional. The number of columns to divide the plotting device in (when plotting multiple layers)} \item{nr}{positive integer. Optional. The number of rows to divide the plotting device in (when plotting multiple layers)} \item{main}{character. Main plot titles (one for each layer to be plotted)} \item{maxnl}{positive integer. Maximum number of layers to plot (for a multi-layer object)} \item{add}{logical. If \code{TRUE} add the object to the current plot} \item{ext}{SpatExtent. Can be use instead of xlim and ylim to set the extent of the plot} \item{reset}{logical. If \code{TRUE} add the margins (see argument \code{mar}) are reset to what they were before calling plot; doing so may affect the display of additional objects that are added to the map (e.g. with \code{\link{lines}}} \item{...}{arguments passed to \code{plot("SpatRaster", "numeric")} and additional graphical arguments} } \seealso{ \code{\link{points}}, \code{\link{lines}}, \code{\link{polys}}, \code{\link{image}}, \code{scatter\link[terra:scatter]{plot}}, \code{\link{sbar}} } \examples{ ## raster f <- system.file("ex/elev.tif", package="terra") r <- rast(f) plot(r) plot(r, type="interval") e <- c(6.3, 6.35, 49.9, 50.1) plot(r, plg=list(ext=e, title="Title\n", title.cex=1.25), pax=list(sides=1:2)) d <- classify(r, c(100,200,300,400,500,600)) plot(d, type="classes") plot(d, type="interval", breaks=1:5) plot(d, type="interval", breaks=c(1,4,5), plg=list(legend=c("1-4", "4-5"))) plot(d, type="classes", plg=list(legend=c("Mr", "Xx", "As", "Zx", "Bb"), x="bottomright")) x <- trunc(r/200) levels(x) <- c("earth", "wind", "fire") plot(x, plg=list(x="topright"),mar=c(2,2,2,2)) # two plots with the same legend dev.new(width=6, height=4, noRStudioGD = TRUE) par(mfrow=c(1,2)) plot(r, range=c(50,600)) plot(r/2, range=c(50,600)) # as you only need one legend: par(mfrow=c(1,2)) plot(r, range=c(50,600), mar=c(4, 3, 4, 3), plg=list(shrink=0.9, cex=.8), pax=list(sides=1:2, cex.axis=.6)) #text(182500, 335000, "Two maps, one plot", xpd=NA) plot(r/2, range=c(50,600), mar=c(4, 2, 4, 4), legend=FALSE, pax=list(sides=c(1,4), cex.axis=.6)) ## multi-layer with RGB s <- rast(system.file("ex/logo.tif", package="terra")) s plot(s) # remove RGB plot(s*1) # or use layers plot(s, 1) plot(s, 1:3) ## vector f <- system.file("ex/lux.shp", package="terra") v <- vect(f) plot(v) plot(v, 2, pax=list(sides=1:2), plg=list(x=6.2, y=50.2, cex=1.2)) plot(v, 4, pax=list(sides=1:2), plg=list(x=6.2, y=50.2, ncol=2), main="") plot(v, 1, plg=list(x=5.9, y=49.37, horiz=TRUE, cex=1.1), main="", mar=c(5,2,0.5,0.5)) plot(v, density=1:12, angle=seq(18, 360, 20), col=rainbow(12)) plot(v, "NAME_2", col=rainbow(12), border=c("gray", "blue"), lwd=3, type="classes") plot(v, "AREA", type="interval", breaks=3, mar=c(3.1, 3.1, 2.1, 3.1), plg=list(x="topright"), main="") plot(v, "AREA", type="interval", breaks=c(0,200,250,350), mar=c(2,2,2,2), plg=list(legend=c("<200", "200-250", ">250"), cex=1, bty="o", x=6.4, y=50.125, box.lwd=2, bg="light yellow", title="My Legend")) } \keyword{methods} \keyword{spatial} terra/man/focal.Rd0000644000175000017500000001032614202017477013655 0ustar nileshnilesh\name{focal} \alias{focal} \alias{focal,SpatRaster-method} \title{Focal values} \description{ Calculate focal ("moving window") values for each cell. } \usage{ \S4method{focal}{SpatRaster}(x, w=3, fun="sum", ..., na.policy="all", fillvalue=NA, expand=FALSE, silent=TRUE, filename="", overwrite=FALSE, wopt=list()) } \arguments{ \item{x}{SpatRaster} \item{w}{window. The window can be defined as one (for a square) or two numbers (row, col); or with an odd-sized weights matrix. See Details.} \item{fun}{function that takes multiple numbers, and returns a numeric vector (one or multiple numbers). For example mean, modal, min or max} \item{...}{additional arguments passed to \code{fun} such as \code{na.rm}} \item{na.policy}{character. Can be used to determine the cells of \code{x} for which focal values should be computed. Must be one of "all" (compute for all cells), "only" (only for cells that are \code{NA}) or "omit" (skip cells that are \code{NA}). Note that the value of this argument does not affect which cells around each focal cell are included in the computations (use \code{na.rm=TRUE} to ignore cells that are \code{NA} for that)} \item{fillvalue}{numeric. The value of the cells in the virtual rows and columns outside of the raster} \item{expand}{logical. If \code{TRUE} The value of the cells in the virtual rows and columns outside of the raster are set to be the same as the value on the border. Only available for "build-in" \code{fun}s such as mean, sum, min and max} \item{silent}{logical. If \code{TRUE} error messages are printed that may occur when trying \code{fun} to determine the length of the returned value. This can be useful in debugging a \code{fun} that does not work} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{additional arguments for writing files as in \code{\link{writeRaster}}} } \details{ \code{focal} The window used must have odd dimensions. If you need even sides, you can use a matrix and add a column or row with weights of zero. Window values are typically 0 or 1, or a value between 0 and 1 if you are using a rectangular area and/or the "sum" function. They can also be \code{NA}; these are ignored in the computation. That can be useful to compute, for example, the minimum or maximum value for a non-rectangular area. The "mean" function is a special case, as zero weights are ignored automatically. The "sum" function returns \code{NA} if all focal cells are \code{NA} and \code{na.rm=TRUE}. R would normally return a zero in thise cases. See the difference between \code{focal(x, fun=sum, na.rm=TRUE} and \code{focal(x, fun=\(i) sum(i, na.rm=TRUE))} Example weight matrices Laplacian filter: \code{filter=matrix(c(0,1,0,1,-4,1,0,1,0), nrow=3)} Sobel filters (for edge detection): \code{fx=matrix(c(-1,-2,-1,0,0,0,1,2,1), nrow=3)} \code{fy=matrix(c(1,0,-1,2,0,-2,1,0,-1), nrow=3)} } \value{SpatRaster} \seealso{ \code{\link{focalMat}}, \code{\link{focalValues}}, \code{\link{focal3D}}, \code{\link{focalCor}}, \code{\link{focalReg}}, \code{\link{focalCpp}} } \examples{ r <- rast(ncols=10, nrows=10, ext(0, 10, 0, 10)) values(r) <- 1:ncell(r) f <- focal(r, w=3, fun=function(x, ...) quantile(x, c(.25, .5, .75), ...), na.rm=TRUE) f <- focal(r, w=3, fun="mean") # the following two statements are equivalent: a <- focal(r, w=matrix(1/9, nc=3, nr=3)) b <- focal(r, w=3, fun=mean, na.rm=FALSE) # but this is different d <- focal(r, w=3, fun=mean, na.rm=TRUE) ## illustrating the effect of different ## combinations of na.rm and na.policy v <- vect(system.file("ex/lux.shp", package="terra")) r <- rast(system.file("ex/elev.tif", package="terra")) r[45:50, 45:50] <- NA # also try "mean" or "min" f <- "sum" # na.rm=FALSE plot(focal(r, 5, f) , fun=lines(v)) # na.rm=TRUE plot(focal(r, 5, f, na.rm=TRUE), fun=lines(v)) # only change cells that are NA plot(focal(r, 5, f, na.policy="only", na.rm=TRUE), fun=lines(v)) # do not change cells that are NA plot(focal(r, 5, f, na.policy="omit", na.rm=TRUE), fun=lines(v)) # does not do anything # focal(r, 5, f, na.policy="only", na.rm=FALSE) } \keyword{spatial} terra/man/atan2.Rd0000644000175000017500000000203714201035747013575 0ustar nileshnilesh\name{atan2} \alias{atan2,SpatRaster,SpatRaster-method} \alias{atan2} \alias{atan_2,SpatRaster,SpatRaster-method} \alias{atan_2} \title{Two argument arc-tangent} \description{ For SpatRasters x and y, atan2(y, x) returns the angle in radians for the tangent y/x, handling the case when x is zero. See \code{\link[base]{Trig}} See \code{\link{Math-methods}} for other trigonometric and mathematical functions that can be used with SpatRasters. } \usage{ \S4method{atan2}{SpatRaster,SpatRaster}(y, x) \S4method{atan_2}{SpatRaster,SpatRaster}(y, x, filename, ...) } \arguments{ \item{y}{SpatRaster} \item{x}{SpatRaster} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \seealso{ \code{\link{Math-methods}} } \examples{ r1 <- rast(nrows=10, ncols=10) r2 <- rast(nrows=10, ncols=10) values(r1) <- (runif(ncell(r1))-0.5) * 10 values(r2) <- (runif(ncell(r1))-0.5) * 10 atan2(r1, r2) } \keyword{math} \keyword{spatial} terra/man/image.Rd0000644000175000017500000000161214201035750013642 0ustar nileshnilesh\name{image} \docType{methods} \alias{image} \alias{image,SpatRaster-method} \title{SpatRaster image method} \description{ Plot (make a map of) the values of a SpatRaster via \code{\link[graphics]{image}}. See \code{\link[terra]{plot}} if you need more fancy options such as a legend. } \usage{ \S4method{image}{SpatRaster}(x, y=1, maxcell=50000, ...) } \arguments{ \item{x}{SpatRaster} \item{y}{positive integer indicating the layer to be plotted, or a character indicating the name of the layer} \item{maxcell}{positive integer. Maximum number of cells to use for the plot} \item{...}{additional arguments as for \code{graphics::\link[graphics]{image}} } } \seealso{ \code{\link[terra]{plot}} } \examples{ f <- system.file("ex/elev.tif", package="terra") r <- rast(f) image(r) image(r, col=rainbow(24)) } \keyword{methods} \keyword{spatial} terra/man/direction.Rd0000644000175000017500000000205714201035750014544 0ustar nileshnilesh\name{direction} \alias{direction} \alias{direction,SpatRaster-method} \title{Direction} \description{ The direction (azimuth) to or from the nearest cell that is not \code{NA}. The direction is expressed in radians, unless you use argument \code{degrees=TRUE}. } \usage{ \S4method{direction}{SpatRaster}(x, from=FALSE, degrees=FALSE, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{filename}{Character. Output filename (optional)} \item{degrees}{Logical. If \code{FALSE} (the default) the unit of direction is radians.} \item{from}{Logical. Default is \code{FALSE}. If \code{TRUE}, the direction from (instead of to) the nearest cell that is not \code{NA} is returned} \item{...}{Additional arguments as for \code{\link{writeRaster}}} } \value{SpatRaster} \seealso{ \code{\link[terra]{distance}} } \examples{ r <- rast(ncol=36,nrow=18, crs="+proj=merc") values(r) <- NA r[306] <- 1 b <- direction(r, degrees=TRUE) plot(b) crs(r) <- "+proj=longlat" b <- direction(r) plot(b) } \keyword{spatial} terra/man/perim.Rd0000644000175000017500000000126014201035750013673 0ustar nileshnilesh\name{perim} \alias{perim} \alias{perim,SpatVector-method} \alias{perimeter} \alias{perimeter,SpatVector-method} \title{Perimeter or length} \description{ This method returns the length of lines or the perimeter of polygons. When the crs is not longitude/latitude, you may get more accurate results by first un-projecting the SpatVector (you can use \code{\link{project}} to transform the crs to longitude/latitude) } \usage{ \S4method{perim}{SpatVector}(x) } \arguments{ \item{x}{SpatVector} } \value{ numeric (m) } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) perim(v) } \keyword{methods} \keyword{spatial} terra/man/extract.Rd0000644000175000017500000001242714202514477014251 0ustar nileshnilesh\name{extract} \docType{methods} \alias{extract} \alias{extract,SpatRaster,SpatVector-method} \alias{extract,SpatRaster,SpatExtent-method} \alias{extract,SpatRaster,matrix-method} \alias{extract,SpatRaster,data.frame-method} \alias{extract,SpatRaster,numeric-method} \alias{extract,SpatVector,SpatVector-method} \alias{[,SpatVector,SpatVector,missing-method} \alias{[,SpatVector,SpatExtent,missing-method} \alias{[,SpatRaster,SpatVector,missing-method} \alias{[,SpatRaster,missing,missing-method} \alias{[,SpatRaster,numeric,missing-method} \alias{[,SpatRaster,missing,numeric-method} \alias{[,SpatRaster,numeric,numeric-method} \alias{[,SpatRaster,data.frame,missing-method} \alias{[,SpatRaster,matrix,missing-method} \alias{[,SpatRaster,SpatRaster,missing-method} \alias{[,SpatRaster,SpatExtent,missing-method} \title{Extract values from a SpatRaster} \description{ Extract values from a SpatRaster for a set of locations. The locations can be a SpatVector (points, lines, polygons), a matrix with (x, y) or (longitude, latitude -- in that order!) coordinates, or a vector with cell numbers. When argument \code{y} is a \code{SpatVector}, and \code{list=FALSE}, the first column has the ID (record number) of the \code{SpatVector} used. } \usage{ \S4method{extract}{SpatRaster,SpatVector}(x, y, fun=NULL, method="simple", list=FALSE, factors=TRUE, cells=FALSE, xy=FALSE, weights=FALSE, exact=FALSE, touches=is.lines(y), layer=NULL, ...) \S4method{extract}{SpatRaster,SpatExtent}(x, y, factors=TRUE, cells=FALSE, xy=FALSE) \S4method{extract}{SpatRaster,matrix}(x, y, ...) \S4method{extract}{SpatRaster,numeric}(x, y, ...) } \arguments{ \item{x}{SpatRaster} \item{y}{SpatVector (for points, lines, polygons), or for points, 2-column matrix or data.frame (x, y) or (lon, lat), or a vector with cell numbers} \item{fun}{function to summarize the data by geometry. If \code{weights=TRUE} or \code{exact=TRUE} only \code{mean}, \code{sum}, \code{min} and \code{max} are accepted)} \item{...}{additional arguments to \code{fun} if \code{y} is a SpatVector. For example \code{na.rm=TRUE}. Or arguments passed to the \code{SpatRaster,SpatVector} method if \code{y} is a matrix (such as the \code{method} and \code{cells} arguments)} \item{method}{character. method for extracting values with points ("simple" or "bilinear"). With "simple" values for the cell a point falls in are returned. With "bilinear" the returned values are interpolated from the values of the four nearest raster cells} \item{list}{logical. If \code{FALSE} the output is simplified to a \code{matrix} (if \code{fun=NULL})} \item{factors}{logical. If \code{TRUE} the categories are returned as factors instead of their numerical representation. The value returned becomes a data.frame if it otherwise would have been a matrix, even if there are no factors} \item{cells}{logical. If \code{TRUE} the cell numbers are also returned, unless \code{fun} is not \code{NULL}. Also see \code{\link{cells}}} \item{xy}{logical. If \code{TRUE} the coordinates of the cells are also returned, unless \code{fun} is not \code{NULL}. Also see \code{\link{xyFromCell}}} \item{weights}{logical. If \code{TRUE} and \code{y} has polygons, the approximate fraction of each cell that is covered is returned as well, for example to compute a weighted mean} \item{exact}{logical. If \code{TRUE} and \code{y} has polygons, the exact fraction of each cell that is covered is returned as well, for example to compute a weighted mean} \item{touches}{logical. If \code{TRUE}, values for all cells touched by lines or polygons are extracted, not just those on the line render path, or whose center point is within the polygon. Not relevant for points; and always considered \code{TRUE} when \code{weights=TRUE} or \code{exact=TRUE}} \item{layer}{character or numeric to select the layer to extract from for each geometry. If \code{layer} is a character it can be a name in \code{y} or a vector of layer names. If it is numeric, it must be integer values between \code{1} and \code{nlyr(x)}} } \value{matrix, list, or data.frame} \seealso{\link{values}} \examples{ r <- rast(ncols=5, nrows=5, xmin=0, xmax=5, ymin=0, ymax=5) values(r) <- 1:25 xy <- rbind(c(0.5,0.5), c(2.5,2.5)) p <- vect(xy, crs="+proj=longlat +datum=WGS84") extract(r, xy) extract(r, p) r[1,] r[5] r[,5] r[c(0:2, 99:101)] f <- system.file("ex/meuse.tif", package="terra") r <- rast(f) xy <- cbind(179000, 330000) xy <- rbind(xy-100, xy, xy+1000) extract(r, xy) p <- vect(xy) g <- geom(p) g extract(r, p) x <- r + 10 extract(x, p) i <- cellFromXY(r, xy) x[i] r[i] y <- c(x,x*2,x*3) y[i] ## extract with a polygon f <- system.file("ex/lux.shp", package="terra") v <- vect(f) v <- v[1:2,] z <- rast(v, resolution=.1, names="test") values(z) <- 1:ncell(z) rf <- system.file("ex/elev.tif", package="terra") x <- rast(rf) extract(x, v, mean, na.rm=TRUE) e <- extract(z, v) e tapply(e[,2], e[,1], mean, na.rm=TRUE) ee <- extract(z, v, list=TRUE) rapply(ee, mean) x <- c(z, z*2, z/3) names(x) <- letters[1:3] e <- extract(x, v) de <- data.frame(e) aggregate(de[,2:4], de[,1,drop=FALSE], mean) ee <- extract(x, v, list=TRUE) matrix(rapply(ee, mean), ncol=nlyr(x), byrow=TRUE) } \keyword{methods} \keyword{spatial} terra/man/clamp.Rd0000644000175000017500000000212614201035750013655 0ustar nileshnilesh\name{clamp} \alias{clamp} \alias{clamp,SpatRaster-method} \alias{clamp,numeric-method} \title{Clamp values} \description{ Clamp values to a minimum and maximum value. That is, all values below a lower threshold value and above the upper threshold value become either \code{NA}, or, if \code{values=TRUE}, become the threshold value } \usage{ \S4method{clamp}{SpatRaster}(x, lower=-Inf, upper=Inf, values=TRUE, filename="", ...) \S4method{clamp}{numeric}(x, lower=-Inf, upper=Inf, values=TRUE, ...) } \arguments{ \item{x}{SpatRaster} \item{lower}{numeric. lowest value} \item{upper}{numeric. highest value} \item{values}{logical. If \code{FALSE} values outside the clamping range become \code{NA}, if \code{TRUE}, they get the extreme values} \item{filename}{character. Output filename} \item{...}{additional argumments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{ \code{\link{classify}} } \examples{ r <- rast(ncols=10, nrows=10) values(r) <- 1:ncell(r) rc <- clamp(r, 25, 75) rc } \keyword{spatial} terra/man/writeCDF.Rd0000644000175000017500000000436314201035750014235 0ustar nileshnilesh\name{writeCDF} \alias{writeCDF} \alias{writeCDF,SpatRasterDataset-method} \alias{writeCDF,SpatRaster-method} \title{Write raster data to a NetCDF file} \description{ Write a SpatRaster or SpatRasterDataset to a NetCDF file. When using a SpatRasterDataset, the varname, longname, and unit should be set in the object (see examples). Always use the \code{".nc"} or \code{".cdf"} file extension to assure that the file can be properly read again by GDAL } \usage{ \S4method{writeCDF}{SpatRaster}(x, filename, varname, longname="", unit="", ...) \S4method{writeCDF}{SpatRasterDataset}(x, filename, overwrite=FALSE, zname="time", prec="float", compression=NA, missval, ...) } \arguments{ \item{x}{SpatRaster or SpatRasterDataset} \item{filename}{character. Output filename} \item{varname}{character. Name of the dataset} \item{longname}{character. Long name of the dataset} \item{unit}{character. Unit of the data} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{zname}{character. The name of the "time" dimension} \item{prec}{character. One of "double", "float", "integer", "short", "byte" or "char"} \item{compression}{Can be set to an integer between 1 (least compression) and 9 (most compression)} \item{missval}{numeric, the number used to indicate missing values} \item{...}{additional arguments passed on to \code{\link[ncdf4]{ncvar_def}}} } \value{ SpatRaster or SpatDataSet } \seealso{ see \code{\link{writeRaster}} for writing other file formats } \examples{ f <- system.file("ex/elev.tif", package="terra") r <- rast(f) fname <- paste0(tempfile(), ".nc") rr <- writeCDF(r, fname, overwrite=TRUE, varname="alt", longname="elevation in m above sea level", unit="m") a <- rast(ncols=5, nrows=5, nl=50) values(a) <- 1:prod(dim(a)) time(a) <- as.Date("2020-12-31") + 1:nlyr(a) aa <- writeCDF(a, fname, overwrite=TRUE, varname="power", longname="my nice data", unit="U/Pa") b <- sqrt(a) s <- sds(a, b) names(s) <- c("temp", "prec") longnames(s) <- c("temperature (C)", "precicpiation (mm)") units(s) <- c("C", "mm") ss <- writeCDF(s, fname, overwrite=TRUE) # for CRAN file.remove(fname) } \keyword{ spatial } \keyword{ methods } terra/man/tmpFile.Rd0000644000175000017500000000274114201035750014164 0ustar nileshnilesh\name{tmpFiles} \alias{tmpFiles} \title{Temporary files} \description{ List and optionally remove temporary files created by the terra package. These files are created when an output SpatRaster may be too large to store in memory (RAM). This can happen when no filename is provided to a function and when using functions where you cannot provide a filename. Temporary files are automatically removed at the end of each R session that ends normally. You can use \code{tmpFiles} to see the files in the current sessions, including those that are orphaned (not connect to a SpatRaster object any more) and from other (perhaps old) sessions, and remove all the temporary files. } \usage{ tmpFiles(current=TRUE, orphan=FALSE, old=FALSE, remove=FALSE) } \arguments{ \item{current}{logical. If \code{TRUE}, temporary files from the current R session are included} \item{orphan}{logical. If \code{TRUE}, temporary files from the current R session that are no longer associated with a SpatRaster object (if \code{current} is \code{TRUE} these are also included)} \item{old}{logical. If \code{TRUE}, temporary files from other "R" sessions. Unless you are running multiple instances of R at the same time, these are from old (possibly crashed) R sessions and should be removed} \item{remove}{logical. If \code{TRUE}, temporary files are removed} } \value{ character } \seealso{ \code{\link{terraOptions}} } \examples{ tmpFiles() } \keyword{ spatial } terra/man/c.Rd0000644000175000017500000000265214201035750013007 0ustar nileshnilesh\name{c} \docType{methods} \alias{c} \alias{c,SpatRaster-method} \alias{c,SpatRasterDataset-method} \alias{c,SpatVector-method} \alias{c,SpatVectorCollection-method} \title{Combine SpatRaster or SpatVector objects} \description{ With \code{c} you can: -- Combine \code{SpatRaster} objects. They must have the same extent and resolution. However, if \code{x} is empty (has no cell values), its geometry is ignored with a warning. Two empty SpatRasters with the same geometry can also be combined (to get a summed number of layers). Also see \code{\link{add<-}} -- Add a \code{SpatRaster} to a \code{SpatRasterDataset} -- Add \code{SpatVector} objects to a new or existing \code{SpatVectorCollection} To append SpatVectors, use \code{rbind}. } \seealso{\code{\link{add<-}}} \usage{ \S4method{c}{SpatRaster}(x, ..., warn=TRUE) \S4method{c}{SpatRasterDataset}(x, ...) \S4method{c}{SpatVector}(x, ...) \S4method{c}{SpatVectorCollection}(x, ...) } \arguments{ \item{x}{SpatRaster, SpatVector, SpatRasterDataset or SpatVectorCollection} \item{warn}{logical. If \code{TRUE}, a warning is emitted if \code{x} is an empty SpatRaster} \item{...}{as for \code{x} (you can only combine raster with raster data and vector with vector data)} } \value{ Same class as \code{x} } \examples{ r <- rast(nrows=5, ncols=9) values(r) <- 1:ncell(r) x <- c(r, r*2, r*3) } \keyword{spatial} terra/man/as.raster.Rd0000644000175000017500000000154114201035747014471 0ustar nileshnilesh\name{as.raster} \alias{as.raster} \alias{as.raster,SpatRaster-method} \title{Coerce to a "raster" object} \description{ Implementation of the generic \code{\link[grDevices]{as.raster}} function to create a "raster" (small r) object. Such objects can be used for plotting with the \code{\link[graphics]{rasterImage}} function. NOT TO BE CONFUSED with the Raster* (big R) objects defined by the 'raster' package! } \usage{ \S4method{as.raster}{SpatRaster}(x, maxcell=500000, col) } \arguments{ \item{x}{ SpatRaster } \item{maxcell}{positive integer. Maximum number of cells to use for the plot} \item{col}{vector of colors. Default is col=rev(terrain.colors(255)))} } \value{ 'raster' object } \examples{ r <- rast(ncols=3, nrows=3) values(r) <- 1:ncell(r) as.raster(r) } \keyword{spatial} \keyword{methods} terra/man/na.omit.Rd0000644000175000017500000000142514201035750014127 0ustar nileshnilesh\name{na.omit} \alias{na.omit} \alias{na.omit,SpatVector-method} \title{na.omit for SpatVector} \description{ Remove empty geometries and/or records that are \code{NA} from a SpatVector. } \usage{ \S4method{na.omit}{SpatVector}(object, field=NA, geom=FALSE) } \arguments{ \item{object}{SpatVector} \item{field}{character or NA. If \code{NA}, missing values in the attributes are ignored. Other values are either one or more field (variable) names, or \code{""} to consider all fields} \item{geom}{logical. If \code{TRUE} empty geometries are removed} } \value{ SpatVector } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) v$test <- c(1,2,NA) nrow(v) x <- na.omit(v, "test") nrow(x) } \keyword{spatial} terra/man/rast.Rd0000644000175000017500000001300614201035750013531 0ustar nileshnilesh\name{rast} \docType{methods} \alias{rast} \alias{rast,missing-method} \alias{rast,character-method} \alias{rast,SpatRaster-method} \alias{rast,SpatRasterDataset-method} \alias{rast,data.frame-method} \alias{rast,matrix-method} \alias{rast,array-method} \alias{rast,list-method} \alias{rast,SpatExtent-method} \alias{rast,SpatVector-method} \alias{rast,ANY-method} \alias{rast,PackedSpatRaster-method} \alias{rast,stars-method} \alias{rast,stars_proxy-method} \title{Create a SpatRaster} \description{ Methods to create a SpatRaster. These objects can be created from scratch, from a filename, or from another object. A SpatRaster represents a spatially referenced surface divided into three dimensional cells (rows, columns, and layers). When a SpatRaster is created from a file, it does not load the cell (pixel) values into memory (RAM). It only reads the parameters that describe the geometry of the SpatRaster, such as the number of rows and columns and the coordinate reference system. The actual values will be read when needed. } \usage{ \S4method{rast}{character}(x, subds=0, lyrs=NULL, opts=NULL) \S4method{rast}{missing}(x, nrows=180, ncols=360, nlyrs=1, xmin=-180, xmax=180, ymin=-90, ymax=90, crs, extent, resolution, vals, names, time, units) \S4method{rast}{SpatRaster}(x, nlyrs=nlyr(x), names, vals, keeptime=TRUE, keepunits=FALSE, props=FALSE) \S4method{rast}{matrix}(x, type="", crs="", digits=6, extent=NULL) \S4method{rast}{data.frame}(x, type="xyz", crs="", digits=6, extent=NULL) \S4method{rast}{array}(x, crs="", extent=NULL) \S4method{rast}{list}(x) \S4method{rast}{SpatRasterDataset}(x) \S4method{rast}{SpatVector}(x, ...) \S4method{rast}{SpatExtent}(x, ...) } \arguments{ \item{x}{filename (character), missing, SpatRaster, SpatRasterDataset, SpatExtent, SpatVector, matrix, array, list of SpatRaster objects. For other types it will be attempted to create a SpatRaster via (`as(x, "SpatRaster")`} \item{subds}{positive integer or character to select a sub-dataset. If zero or "", all sub-datasets are returned (if possible)} \item{lyrs}{positive integer or character to select a subset of layers (a.k.a. "bands")} \item{opts}{character. GDAL dataset open options} \item{nrows}{positive integer. Number of rows} \item{ncols}{positive integer. Number of columns} \item{nlyrs}{positive integer. Number of layers} \item{xmin}{minimum x coordinate (left border)} \item{xmax}{maximum x coordinate (right border)} \item{ymin}{minimum y coordinate (bottom border)} \item{ymax}{maximum y coordinate (top border)} \item{crs}{character. Description of the Coordinate Reference System (map projection) in \code{PROJ.4}, \code{WKT} or \code{authority:code} notation. If this argument is missing, and the x coordinates are within -360 .. 360 and the y coordinates are within -90 .. 90, longitude/latitude is assigned} \item{keeptime}{logical. If \code{FALSE} the time stamps are discarded} \item{keepunits}{logical. If \code{FALSE} the layer units are discarded} \item{props}{logical. If \code{TRUE} the properties (categories and color-table) are kept} \item{extent}{object of class SpatExtent. If present, the arguments xmin, xmax, ymin and ymax are ignored} \item{resolution}{numeric vector of length 1 or 2 to set the resolution (see \code{\link{res}}). If this argument is used, arguments \code{ncol} and \code{nrow} are ignored } \item{vals}{numeric. An optional vector with cell values (if fewer values are provided, these are recycled to reach the number of cells)} \item{names}{character. An optional vector with layer names (must match the number of layers)} \item{time}{time or date stamps for each layer} \item{units}{character. units for each layer} \item{type}{character. If the value is not \code{"xyz"}, the raster has the same number of rows and colums as the matrix. If the value is \code{"xyz"}, the matrix must have at least two columns, the first with \code{x} (or longitude) and the second with \code{y} (or latitude) coordinates that represent the centers of raster cells. The additional columns are the values associated with the raster cells.} \item{digits}{integer to set the precision for detecting whether points are on a regular grid (a low number of digits is a low precision). Only used when \code{type="xyz"}} \item{...}{additional arguments passed on to the \code{rast,missing-method}} } \value{ SpatRaster } \details{ Files are read with the GDAL library. GDAL guesses the file format from the name, and/or tries reading it with different "drivers" (see \code{\link{gdal}}) until it succeeds. In very few cases this may cause a file to be opened with the wrong driver, and some information may be lost. For example, when a netCDF file is opened with the HDF5 driver. You can avoid that by prepending the driver name to the filename like this: \code{rast('NETCDF:"filename.ncdf"')} } \seealso{\code{\link{sds}} to create a SpatRasterDataset (4 dimensions) and \code{\link{vect}} for vector (points, lines, polygons) data} \examples{ # Create a SpatRaster from scratch x <- rast(nrows=108, ncols=21, xmin=0, xmax=10) # Create a SpatRaster from a file f <- system.file("ex/elev.tif", package="terra") r <- rast(f) s <- rast(system.file("ex/logo.tif", package="terra")) # Create a skeleton with no associated cell values rast(s) # from a matrix m <- matrix(1:25, nrow=5, ncol=5) rm <- rast(m) # from a "xyz" data.frame d <- as.data.frame(rm, xy=TRUE) head(d) rast(d, type="xyz") } \keyword{methods} \keyword{spatial} terra/man/headtail.Rd0000644000175000017500000000143514201035750014336 0ustar nileshnilesh\name{head and tail} \docType{methods} \alias{head} \alias{head,SpatRaster-method} \alias{head,SpatVector-method} \alias{tail} \alias{tail,SpatRaster-method} \alias{tail,SpatVector-method} \title{Show the head or tail of a Spat* object} \description{ Show the head (first values) or tail (last values) of a SpatRaster or of the attributes of a SpatVector. } \usage{ head(x, ...) tail(x, ...) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{...}{additional arguments passed on to other methods} } \value{ matrix (SpatRaster) or data.frame (SpatVector) } \seealso{ \code{\link{show}}, \code{\link{geom}} } \examples{ r <- rast(nrows=25, ncols=25) values(r) <- 1:ncell(r) head(r) tail(r) } \keyword{methods} \keyword{spatial} terra/man/terra-package.Rd0000644000175000017500000010202314201035750015264 0ustar nileshnilesh\name{terra-package} \alias{terra-package} \alias{terra} \docType{package} \title{The terra package} \description{ \code{terra} provides methods to manipulate geographic (spatial) data in "raster" and "vector" form. Raster data divide space into rectangular cells (pixels) and they are commonly used to represent spatially continuous phenomena, such as elevation or the weather. Satellite images also have this data structure. In contrast, "vector" spatial data (points, lines, polygons) are typically used to represent discrete spatial entities, such as a road, country, or bus stop. The package implements two main classes (R data types): \code{SpatRaster} and \code{SpatVector}. \code{SpatRaster} supports handling large raster files that cannot be loaded into memory; local, focal, zonal, and global raster operations; polygon, line and point to raster conversion; integration with modeling methods to make spatial predictions; and more. \code{SpatVector} supports all types of geometric operations such as intersections. Additional classes include \code{SpatExtent}, which is used to define a spatial extent (bounding box); \code{SpatRasterDataset}, which represents a collection of sub-datasets for the same area. Each sub-dataset is a SpatRaster with possibly many layers, and may, for example, represent different weather variables; and \code{SpatRasterCollection} and \code{SpatVectorCollection} that are equivalent to lists of SpatRaster or SpatVector objects. These classes hold a C++ pointer to the data and they cannot be directly saved to a ".Rds" file or used in cluster computing. They cannot be recovered from a saved R session either. See \code{\link{wrap}} or \code{\link{writeRaster}} to work around that limitation. The \code{terra} package is conceived as a replacement of the \code{raster} package. \code{terra} has a very similar, but simpler, interface, and it is faster than \code{raster}. At the bottom of this page there is a table that shows differences in the methods between the two packages. Below is a list of some of the most important methods grouped by theme. } \section{}{ --------------------------------------------------------------------------------------------------------------------- \bold{SpatRaster} ---------------------------------------------------------------------------------------------------------------------} \section{I. Creating, combining and sub-setting}{ \tabular{ll}{ \code{\link{rast}}\tab Create a SpatRaster from scratch, file, or another object\cr \code{\link{c}} \tab Combine SpatRasters (multiple layers)\cr \code{\link{add<-}} \tab Add a SpatRaster to another one\cr \code{\link{subset}} or \code{[[}, or \code{$} \tab Select layers of a SpatRaster\cr \code{\link{selectRange}} \tab Select cell values from different layers using an index layer\cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr } } \section{II. Changing the spatial extent or resolution}{ Also see the methods in section VIII \tabular{ll}{ \code{\link{merge}} \tab Combine SpatRasters with different extents (but same origin and resolution) \cr \code{\link{mosaic}} \tab Combine SpatRasters with different extents using a function for overlapping cells \cr \code{\link{crop}} \tab Select a geographic subset of a SpatRaster \cr \code{\link{extend}} \tab Add rows and/or columns to a SpatRaster \cr \code{\link{trim}} \tab Trim a SpatRaster by removing exterior rows and/or columns that only have NAs\cr \code{\link{aggregate}} \tab Combine cells of a SpatRaster to create larger cells \cr \code{\link{disagg}} \tab Subdivide cells \cr \code{\link{resample}} \tab Resample (warp) values to a SpatRaster with a different origin and/or resolution \cr \code{\link{project}} \tab Project (warp) values to a SpatRaster with a different coordinate reference system \cr \code{\link{shift}} \tab Adjust the location of SpatRaster \cr \code{\link{flip}} \tab Flip values horizontally or vertically \cr \code{\link{rotate}} \tab Rotate values around the date-line (for lon/lat data) \cr \code{\link{t}} \tab Transpose a SpatRaster\cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr } } \section{III. Local (cell based) methods}{ \subsection{Apply-like methods}{ \tabular{ll}{ \code{\link{app}} \tab Apply a function to all cells, across layers, typically to summarize (as in \code{base::apply}) \cr \code{\link{tapp}} \tab Apply a function to groups of layers (as in \code{base::tapply} and \code{stats::aggregate})\cr \code{\link{lapp}} \tab Apply a function to using the layers of a SpatRaster as variables\cr \code{\link{sapp}} \tab Apply a function to each layer\cr \code{\link{rapp}} \tab Apply a function to a spatially variable range of layers\cr } } \subsection{Arithmetic, logical, and standard math methods}{ \tabular{ll}{ \code{\link{Arith-methods}} \tab Standard arithmetic methods (\code{+, -, *, ^, \%\%, \%/\%, /}) \cr \code{\link{Compare-methods}} \tab Comparison methods for SpatRaster (\code{==, !=, >, <, <=, >=}) \cr \code{\link{Logic-methods}} \tab Boolean methods (\code{!, &, |}) \cr \code{\link{Math-methods}} \tab \code{abs, sign, sqrt, ceiling, floor, trunc, cummax, cummin, cumprod,} \cr \tab \code{cumsum, log, log10, log2, log1p, acos, acosh, asin, asinh, atan, atanh,} \cr \tab \code{exp, expm1, cos, cosh, sin, sinh, tan, tanh, round, signif}\cr \code{\link{Summary-methods}} \tab \code{mean, max, min, median, sum, range, prod,} \cr \tab \code{any, all, stdev, which.min, which.max}\cr \code{\link{as.bool}}\tab create a Boolean (logical) SpatRaster \cr \code{\link{as.int}}\tab create an integer (whole numbers) SpatRaster \cr } } \subsection{Other methods}{ \tabular{ll}{ \code{\link{approximate}} \tab Compute missing values for cells by interpolation across layers \cr \code{\link{cellSize}} \tab Compute the area of cells \cr \code{\link{classify}} \tab (Re-)classify values \cr \code{\link{cover}} \tab First layer covers second layer except where the first layer is \code{NA} \cr \code{\link{init}} \tab Initialize cells with new values \cr \code{\link{mask}} \tab Replace values in a SpatRaster based on values in another SpatRaster\cr \code{\link{subst}} \tab Substitute (replace) cell values \cr \code{\link{which.lyr}} \tab which is the first layer that is \code{TRUE}?\cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr } } } \section{IV. Zonal and global methods}{ \tabular{ll}{ \code{\link{expanse}} \tab Compute the summed area of cells \cr \code{\link{crosstab}} \tab Cross-tabulate two SpatRasters\cr \code{\link{freq}} \tab Frequency table of SpatRaster cell values \cr \code{\link{global}} \tab Summarize SpatRaster cell values with a function \cr \code{\link{quantile}} \tab Quantiles \cr \code{\link{layerCor}} \tab Correlation between layers \cr \code{\link{stretch}} \tab Stretch values \cr \code{\link{scale}} \tab Scale values \cr \code{\link[terra]{summary}} \tab Summary of the values of a SpatRaster (quartiles and mean) \cr \code{\link{unique}} \tab Get the unique values in a SpatRaster \cr \code{\link{zonal}} \tab Summarize a SpatRaster by zones in another SpatRaster \cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr } } \section{V. Situation (spatial context) based methods}{ \tabular{ll}{ \code{\link{adjacent}} \tab Identify cells that are adjacent to a set of cells of a SpatRaster \cr \code{\link{boundaries}} \tab Detection of boundaries (edges)\cr \code{\link{distance}} \tab Shortest distance to a cell that is not \code{NA} or to or from a vector object\cr \code{\link{direction}} \tab Direction (azimuth) to or from cells that are not \code{NA}\cr \code{\link{focal}} \tab Focal (neighborhood; moving window) functions \cr \code{\link{focalCpp}} \tab Faster focal by using custom C++ functions \cr \code{\link{focalReg}} \tab Regression beween layers for focal areas \cr \code{\link{focalCor}} \tab Correlation between layers for focal areas \cr \code{\link{patches}} \tab Find patches (clumps) \cr \code{\link{terrain}} \tab Compute slope, aspect and other terrain characteristics from elevation data \cr \code{\link{shade}} \tab Compute hill shade from slope and aspect layers \cr \code{\link{autocor}} \tab Compute global or local spatial autocorrelation \cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr } } \section{VI. Model predictions}{ \tabular{ll}{ \code{\link{predict}} \tab Predict a non-spatial model to a SpatRaster \cr \code{\link{interpolate}} \tab Predict a spatial model to a SpatRaster \cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr } } \section{VII. Accessing cell values}{ Apart from the function listed below, you can also use indexing with \code{[} with cell numbers, and row and/or column numbers \cr \tabular{ll}{ \code{\link{values}} \tab cell values (fails with very large rasters)\cr \code{\link{values<-}} \tab Set new values to the cells of a SpatRaster \cr \code{\link{setValues}} \tab Set new values to the cells of a SpatRaster \cr \code{\link{as.matrix}} \tab Get cell values as a matrix \cr \code{\link{as.array}} \tab Get cell values as an array \cr \code{\link{extract}} \tab Extract cell values from a SpatRaster (e.g., by cell, coordinates, polygon)\cr \code{\link{spatSample}} \tab Regular or random sample \cr \code{\link{minmax}} \tab Get the minimum and maximum value of the cells of a SpatRaster (if known) \cr \code{\link{setMinMax}} \tab Compute the minimum and maximum value of a SpatRaster if these are not known \cr \code{\link{extract}} \tab spatial queries of a SpatRaster with a SpatVector\cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr } } \section{VIII. Getting and setting dimensions }{ Get or set basic parameters of SpatRasters. If there are values associated with a SpatRaster object (either in memory or via a link to a file) these are lost when you change the number of columns or rows or the resolution. This is not the case when the extent is changed (as the number of columns and rows will not be affected). Similarly, with \bold{crs} you can set the coordinate reference system, but this does not transform the data (see \link{project} for that). \tabular{ll}{ \code{\link{ncol}}\tab The number of columns \cr \code{\link{nrow}} \tab The number of rows \cr \code{\link{ncell}} \tab The number of cells (can not be set directly, only via ncol or nrow) \cr \code{\link{res}} \tab The resolution (x and y) \cr \code{\link{nlyr}} \tab Get or set the number of layers \cr \code{\link{names}} \tab Get or set the layer names \cr \code{\link{xres}} \tab The x resolution (can be set with res) \cr \code{\link{yres}} \tab The y resolution (can be set with res)\cr \code{\link{xmin}} \tab The minimum x coordinate (or longitude) \cr \code{\link{xmax}} \tab The maximum x coordinate (or longitude) \cr \code{\link{ymin}} \tab The minimum y coordinate (or latitude) \cr \code{\link{ymax}} \tab The maximum y coordinate (or latitude) \cr \code{\link{ext}} \tab Get or set the extent (minimum and maximum x and y coordinates ("bounding box") \cr \code{\link{origin}} \tab The origin of a SpatRaster\cr \code{\link{crs}} \tab The coordinate reference system (map projection) \cr \code{\link{is.lonlat}} \tab Test if an object has (or may have) a longitude/latitude coordinate reference system\cr \code{\link{sources}} \tab Get the filename(s) to which a SpatRaster is linked \cr \code{\link{inMemory}} \tab Are the data sources in memory (or on disk)? \cr \code{\link{compareGeom}} \tab Compare the geometry of SpatRasters \cr \code{\link{NAflag}} \tab Set the \code{NA} value (for reading from a file with insufficient metadata) \cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr } } \section{IX. Computing row, column, cell numbers and coordinates}{ Cell numbers start at 1 in the upper-left corner. They increase within rows, from left to right, and then row by row from top to bottom. Likewise, row numbers start at 1 at the top of the raster, and column numbers start at 1 at the left side of the raster. \tabular{ll}{ \code{\link{xFromCol}} \tab x-coordinates from column numbers \cr \code{\link{yFromRow}} \tab y-coordinates from row numbers \cr \code{\link{xFromCell}} \tab x-coordinates from row numbers \cr \code{\link{yFromCell}} \tab y-coordinates from cell numbers \cr \code{\link{xyFromCell}} \tab x and y coordinates from cell numbers \cr \code{\link{colFromX}} \tab Column numbers from x-coordinates (or longitude) \cr \code{\link{rowFromY}} \tab Row numbers from y-coordinates (or latitude) \cr \code{\link{rowColFromCell}} \tab Row and column numbers from cell numbers\cr \code{\link{cellFromXY}} \tab Cell numbers from x and y coordinates \cr \code{\link{cellFromRowCol}} \tab Cell numbers from row and column numbers \cr \code{\link{cellFromRowColCombine}} \tab Cell numbers from all combinations of row and column numbers \cr \code{\link{cells}}\tab Cell numbers from an SpatVector or SpatExtent\cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr } } \section{X. Writing SpatRaster files}{ \subsection{Basic}{ \tabular{ll}{ \code{\link{writeRaster}} \tab Write all values of SpatRaster to disk. You can set the filetype, datatype, compression. \cr \code{\link{writeCDF}} \tab Write SpatRaster data to a netCDF file\cr } } \subsection{Advanced}{ \tabular{ll}{ \code{\link{writeStart}} \tab Open a file for writing \cr \code{\link{writeValues}} \tab Write some values \cr \code{\link{writeStop}} \tab Close the file after writing \cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr } } } \section{XI. Time related methods}{ \tabular{ll}{ \code{\link{time}} \tab Get or set time\cr \code{\link{fillTime}} \tab can add empty layers in between existing layers to assure that the time step between layers is constant \cr \code{\link{mergeTime}} \tab combine multiple rasters, perhaps partly overlapping in time, into a single time series\cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr } } \section{XII. Miscellaneous SpatRaster methods}{ \tabular{ll}{ \code{\link{terraOptions}} \tab Show, set, or get session options, mostly to control memory use and to set write options\cr \code{\link{sources}} \tab Show the data sources of a SpatRaster \cr \code{\link{tmpFiles}} \tab Show or remove temporary files \cr \code{\link{mem_info}} \tab memory needs and availability \cr \code{\link{readStart}} \tab Open file connections for efficient multi-chunk reading \cr \code{\link{readStop}} \tab Close file connections \cr \code{\link{inMemory}} \tab Are the cell values in memory? \cr } } \section{}{ --------------------------------------------------------------------------------------------------------------------- \bold{SpatRasterDataSet} ---------------------------------------------------------------------------------------------------------------------} \section{XIII. SpatRasterDataset}{ A SpatRasterDataset contains SpatRaster objects that are sub-datasets for the same area. They all have the same extent and resolution. \tabular{ll}{ \code{\link{sds}} \tab Create a SpatRasterDataset from a file with subdatasets (ncdf or hdf) or from SpatRaster objects \cr \code{[} or \code{$} \tab Extract a SpatRaster \cr \code{\link{names}} \tab Get the names of the sub-datasets \cr } } \section{}{ --------------------------------------------------------------------------------------------------------------------- \bold{SpatVector} ---------------------------------------------------------------------------------------------------------------------} \section{XIV. Create SpatVector objects}{ \tabular{ll}{ \code{\link{vect}} \tab Create a SpatVector from a file (for example a "shapefile") or from another object\cr \code{rbind} \tab append SpatVectors of the same geometry type\cr \code{\link{unique}} \tab remove duplicates \cr \code{\link{na.omit}} \tab remove empty geometries and/or fields that are \code{NA} \cr \code{\link{project}} \tab Project a SpatVector to a different coordinate reference system \cr \code{\link{writeVector}} \tab Write SpatVector data to disk \cr \code{\link{centroids}} \tab Get the centroids of a SpatVector\cr \code{\link{voronoi}} \tab Voronoi diagram \cr \code{\link{delauny}} \tab Delauny triangles\cr \code{\link{convHull}} \tab Compute the convex hull of a SpatVector \cr \code{\link{fillHoles}}\tab Remove or extract holes from polygons\cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr }} \section{XV. Properties of SpatVector objects}{ \tabular{ll}{ \code{\link{geom}} \tab returns the geometries as matrix or WKT\cr \code{\link{crds}} \tab returns the coordinates as a matrix\cr \code{\link{linearUnits}} \tab returns the linear units of the crs (in meter)\cr \code{\link{ncol}}\tab The number of columns (of the attributes)\cr \code{\link{nrow}} \tab The number of rows (of the geometries and attributes)\cr \code{\link{names}} \tab Get or set the layer names \cr \code{\link{ext}} \tab Get the extent (minimum and maximum x and y coordinates ("bounding box") \cr \code{\link{crs}} \tab The coordinate reference system (map projection) \cr \code{\link{is.lonlat}} \tab Test if an object has (or may have) a longitude/latitude coordinate reference system\cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr }} \section{XVI. Geometric queries}{ \tabular{ll}{ \code{\link{adjacent}} \tab find adjacent polygons\cr \code{\link{expanse}} \tab computes the area covered by polygons\cr \code{\link{nearby}} \tab find nearby geometries\cr \code{\link{nearest}} \tab find the nearest geometries\cr \code{\link{relate}} \tab geometric relationships such as "intersects", "overlaps", and "touches"\cr \code{\link{perim}} \tab computes the length of the perimeter of polygons, and the length of lines\cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr }} \section{XVII. Geometric operations}{ \tabular{ll}{ \code{\link{erase}} or "-" \tab erase (parts of) geometries\cr \code{\link{intersect}} or "*" \tab intersect geometries\cr \code{\link{union}} or "+" \tab Merge geometries\cr \code{\link{cover}} \tab update polygons\cr \code{\link{symdif}} \tab symmetrical difference of two polygons \cr \code{\link{aggregate}} \tab dissolve smaller polygons into larger ones \cr \code{\link{buffer}} \tab buffer geometries \cr \code{\link{disagg}} \tab split multi-geometries into separate geometries \cr \code{\link{crop}} \tab clip geometries using a rectangle (SpatExtent) or SpatVector \cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr }} \section{XVIII. SpatVector attributes}{ We use the term "attributes" for the tabular data (data.frame) associated with vector geometries. \tabular{ll}{ \code{\link{extract}} \tab spatial queries between SpatVector and SpatVector (e.g. point in polygons) \cr \code{\link{sel}} \tab select - interactively select geometries\cr \code{\link{click}} \tab identify attributes by clicking on a map\cr \code{\link{merge}} \tab Join a table with a SpatVector \cr \code{\link{as.data.frame}} \tab get attributes as a data.frame\cr \code{\link{as.list}} \tab get attributes as a list\cr \code{\link{values}} \tab Get the attributes of a SpatVector \cr \code{\link{values<-}} \tab Set new attributes to the geometries of a SpatRaster \cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr }} \section{XIX. Change geometries (for display, experimentation)}{ \tabular{ll}{ \code{\link{shift}} \tab change the position geometries by shifting their coordinates in horizontal and/or vertical direction\cr \code{\link{spin}}\tab rotate geometries around an origin\cr \code{\link{rescale}} \tab shrink (or expand) geometries, for example to make an inset map \cr \code{\link{flip}} \tab flip geometries vertically or horizontally\cr \code{\link{t}} \tab transpose geometries (switch x and y)\cr }} \section{XX. Geometry properties and topology}{ \tabular{ll}{ \code{\link{width}} \tab the minimum diameter of the geometries \cr \code{\link{clearance}} \tab the minimum clearance of the geometries \cr \code{\link{sharedPaths}} \tab shared paths (arcs) between line or polygon geometries\cr \code{\link{simplifyGeom}} \tab simplify geometries\cr \code{\link{gaps}} \tab find gaps between polygon geometries \cr \code{\link{fillHoles}} \tab get or remove the polygon holes\cr \code{\link{makeNodes}} \tab create nodes on lines \cr \code{\link{mergeLines}} \tab connect lines to form polygons \cr \code{\link{removeDupNodes}} \tab remove duplicate nodes in geometries and optionally rounds the coordinates \cr \code{\link{is.valid}} \tab check if geometries are valid \cr \code{\link{makeValid}} \tab attempt to repair invalid geometries \cr \code{\link{snap}} \tab make boundaries of geometries identical if they are very close to each other \cr \code{\link{erase} (single argument)} \tab remove parts of geometries that overlap \cr \code{\link{union} (single argument)} \tab create new polygons such that there are no overlapping polygons \cr }} \section{}{ --------------------------------------------------------------------------------------------------------------------- \bold{Spat* Collections} ---------------------------------------------------------------------------------------------------------------------} \section{XXI. Collections}{ A SpatRasterCollection is a vector of SpatRaster objects. Unlike for a SpatRasterDataset, there the extent and resolution of the SpatRasters do not need to match each other. A SpatVectorCollection is a vector of SpatVector objects. \tabular{ll}{ \code{\link{svc}} \tab create a SpatRasterCollection from a set of SpatRaster objects\cr \code{\link{length}} \tab how many SpatRasters does the SpatRasterCollection have?\cr \code{\link{[}} \tab extract a SpatRastert\cr }} \section{}{ --------------------------------------------------------------------------------------------------------------------- \bold{SpatExtent} ---------------------------------------------------------------------------------------------------------------------} \section{XXII. SpatExtent}{ \tabular{ll}{ \code{\link{ext}} \tab Create a SpatExtent object. For example to \code{\link{crop}} a Spatial dataset\cr \code{\link{intersect}} \tab Intersect two SpatExtent objects, same as \code{-} \cr \code{\link{union}} \tab Combine two SpatExtent objects, same as \code{+} \cr \code{\link{Math-methods}} \tab round/floor/ceiling of a SpatExtent \cr \code{\link{align}} \tab Align a SpatExtent with a SpatRaster \cr \code{\link{draw}} \tab Create a SpatExtent by drawing it on top of a map (plot) \cr } } \section{}{ --------------------------------------------------------------------------------------------------------------------- \bold{General methods} ---------------------------------------------------------------------------------------------------------------------} \section{XXIII. Conversion between spatial data objects from different packages}{ You can coerce SpatRasters to Raster* objects after loading the \code{raster} package with \code{as(object, "Raster")}, or \code{raster(object)} or \code{brick(object)} or \code{stack(object)} \tabular{ll}{ \code{\link{rast}} \tab SpatRaster from matrix and other objects\cr \code{\link{vect}} \tab SpatVector from \code{sf} or \code{Spatial*} vector data\cr \code{sf::st_as_sf} \tab sf object from SpatVector\cr \code{\link{rasterize}} \tab Rasterizing points, lines or polygons\cr \code{\link{as.points}} \tab Create points from a SpatRaster or SpatVector \cr \code{\link{as.lines}} \tab Create points from a SpatRaster or SpatVector\cr \code{\link{as.polygons}} \tab Create polygons from a SpatRaster \cr \code{\link{as.contour}} \tab Contour lines from a SpatRaster \cr --------------------------- \tab ------------------------------------------------------------------------------------------ \cr } } \section{XXIV. Plotting}{ \subsection{Maps}{ \tabular{ll}{ \code{\link{plot}} \tab Plot a SpatRaster or SpatVector. The main method to create a map \cr \code{\link{points}} \tab Add points to a map\cr \code{\link{lines}} \tab Add lines to a map\cr \code{\link{polys}} \tab Add polygons to a map \cr \code{\link{text}} \tab Add text (such as the values of a SpatRaster or SpatVector) to a map \cr \code{\link{image}} \tab Alternative to plot to make a map with a SpatRaster \cr \code{\link{plotRGB}} \tab Combine three layers (red, green, blue channels) into a single "real color" plot \cr \code{\link{sbar}} \tab Add a scalebar to a map\cr \code{\link{north}} \tab Add a north arrow to a map\cr \code{\link{inset}} \tab Add a small inset (overview) map\cr \code{\link{dots}} \tab Make a dot-density map \cr \code{\link{cartogram}} \tab Make a cartogram \cr \code{\link{persp}} \tab Perspective plot of a SpatRaster \cr \code{\link{contour}} \tab Contour plot or filled-contour plot of a SpatRaster \cr \code{\link{RGB2col}} \tab Combine three layers (red, green, blue channels) into a single layer with a color-table \cr } } \subsection{Interacting with a map}{ \tabular{ll}{ \code{\link{zoom}} \tab Zoom in to a part of a map by drawing a bounding box on it \cr \code{\link{click}} \tab Query values of SpatRaster or SpatVector by clicking on a map \cr \code{\link{sel}} \tab Select a spatial subset of a SpatRaster or SpatVector by drawing on a map\cr \code{\link{draw}} \tab Create a SpatExtent or SpatVector by drawing on a map \cr } } \subsection{Other plots}{ \tabular{ll}{ \code{\link{plot}} \tab x-y scatter plot of the values of (a sample of) the layers of two SpatRaster objects\cr \code{\link{hist}} \tab Histogram of SpatRaster values \cr \code{\link{barplot}} \tab Bar plot of a SpatRaster \cr \code{\link{density}} \tab Density plot of SpatRaster values \cr \code{\link{pairs}} \tab Pairs plot for layers in a SpatRaster \cr \code{\link{boxplot}} \tab Box plot of the values of a SpatRaster\cr } } } \section{}{ --------------------------------------------------------------------------------------------------------------------- \bold{Comparison with the raster package} ---------------------------------------------------------------------------------------------------------------------} \section{XXV. New method names}{ \code{terra} has a single class \code{SpatRaster} for which \code{raster} has three (\code{RasterLayer, RasterStack, RasterBrick}). Likewise there is a single class for vector data \code{SpatVector} that replaces six \code{Spatial*} classes. Most method names are the same, but note the following important differences in methods names with the \code{raster} package \tabular{ll}{ \bold{raster package} \tab \bold{terra package}\cr \code{raster, brick, stack}\tab\code{\link{rast}}\cr \code{rasterFromXYZ}\tab\code{\link{rast}( , type="xyz")}\cr \code{stack, addLayer} (combining Raster* objects or files)\tab\code{\link{c}}\cr \code{addLayer} \tab\code{\link{add<-}}\cr \code{area} \tab\code{\link{cellSize}}\cr \code{approxNA} \tab\code{\link{approximate}}\cr \code{calc}\tab\code{\link{app}}\cr \code{cellFromLine, cellFromPolygon, cellsFromExtent}\tab\code{\link{cells}}\cr \code{cellStats}\tab\code{\link{global}}\cr \code{corLocal}\tab\code{\link{focalCor}}\cr \code{coordinates}\tab\code{\link{crds}}\cr \code{clump}\tab\code{\link{patches}}\cr \code{compareRaster}\tab\code{\link{compareGeom}}\cr \code{disaggregate} \tab\code{\link{disagg}}\cr \code{drawExtent, drawPoly, drawLine} \tab \code{\link{draw}}\cr \code{dropLayer}\tab\code{\link{subset}}\cr \code{extent}\tab\code{\link{ext}}\cr \code{gridDistance, distanceFromPoints} \tab \code{\link{distance}}\cr \code{isLonLat, isGlobalLonLat, couldBeLonLat}\tab\code{\link{is.lonlat}}\cr \code{layerize}\tab\code{\link{segregate}}\cr \code{layerStats}\tab\code{\link{layerCor}}\cr \code{NAvalue}\tab\code{\link{NAflag}}\cr \code{nlayers}\tab\code{\link{nlyr}}\cr \code{overlay}\tab\code{\link{lapp}}\cr \code{projectRaster}\tab\code{\link{project}}\cr \code{rasterToPoints}\tab\code{\link{as.points}}\cr \code{rasterToPolygons}\tab\code{\link{as.polygons}}\cr \code{reclassify, subs, cut}\tab\code{\link{classify}}\cr \code{sampleRandom, sampleRegular}\tab\code{\link{spatSample}}\cr \code{shapefile}\tab\code{\link{vect}}\cr \code{stackApply}\tab\code{\link{tapp}}\cr \code{stackSelect}\tab\code{\link{selectRange}}\cr } } \section{XXVI. Changed behavior}{ Also note that even if function names are the same in \code{terra} and \code{raster}, their output can be different. In most cases this was done to get more consistency in the returned values (and thus fewer errors in the downstream code that uses them). It other cases it simply seemed better. Here are some examples: \tabular{ll}{ \code{\link{as.polygons}}\tab By default, \code{terra} returns dissolved polygons\cr \code{\link{quantile}}\tab computes by cell, across layers instead of the other way around\cr \code{\link{extract}}\tab By default, \code{terra} returns a matrix, with the first column the sequential ID of the vectors. \cr \tab \code{raster} returns a list (for lines or polygons) or a matrix (for points, but without the ID\cr \tab column. You can use \code{list=TRUE} to get the results as a list\cr \code{\link{values}}\tab \code{terra} always returns a matrix. \code{raster} returns a vector for a \code{RasterLayer}\cr \code{\link{Summary-methods}}\tab With \code{raster}, \code{mean(x, y)} and \code{mean(stack(x, y)} return the same result, a single\cr \tab layer with the mean of all cell values. This is also what \code{terra} returns with \cr \tab \code{mean(c(x, y))}, but with \code{mean(x, y)} the parallel mean is returned -- that is, the\cr \tab computation is done layer-wise, and the number of layers in the output is the same as\cr \tab that of \code{x} and \code{y} (or the larger of the two if they are not the same). This affects \cr \tab all summary functions (\code{sum}, \code{mean}, \code{median}, \code{which.min}, \code{which.max}, \code{min}, \code{max},\cr \tab \code{prod}, \code{any}, \code{all}, \code{stdev}), except \code{range}, which is not implemented for this case \cr \tab (you can use \code{min} and \code{max} instead) \cr } } \section{}{ ---------------------------------------------------------------------------------------------------------------------} \section{Author}{ Except where indicated otherwise, the methods and functions in this package were written by Robert Hijmans. The configuration scripts were written by Roger Bivand for \code{rgdal} and \code{sf}. Some of the C++ code for GDAL/GEOS was adapted from code by Edzer Pebesma for \code{sf}. The gridDistance method was based on code by Jacob van Etten. The progress bar code is by Karl Forner (RcppProgress). Jeroen Ooms provided the compiled GDAL and GEOS libraries for installation on windows} \section{Acknowledgments}{ This package is an attempt to climb on the shoulders of giants (GDAL, PROJ, GEOS, NCDF, GeographicLib, Rcpp, R). Many people have contributed by asking questions or \href{https://github.com/rspatial/terra}{raising issues}. Feedback and suggestions by Márcia Barbosa, Kendon Bell, Jean-Luc Dupouey, Krzysztof Dyba, Alex Ilich, Jakub Nowosad, Gerald Nelson, and Michael Sumner have been especially helpful. } \keyword{ package } \keyword{ spatial } terra/man/boundaries.Rd0000644000175000017500000000302414201035750014712 0ustar nileshnilesh\name{boundaries} \alias{boundaries} \alias{boundaries,SpatRaster-method} \title{Detect boundaries (edges)} \description{ Detect boundaries (edges). Boundaries are cells that have more than one class in the 4 or 8 cells surrounding it, or, if \code{classes=FALSE}, cells with values and cells with \code{NA}. } \usage{ \S4method{boundaries}{SpatRaster}(x, classes=FALSE, inner=TRUE, directions=8, falseval=0, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{inner}{logical. If \code{TRUE}, "inner" boundaries are returned, else "outer" boundaries are returned} \item{classes}{character. Logical. If \code{TRUE} all different values are (after rounding) distinguished, as well as \code{NA}. If \code{FALSE} (the default) only edges between \code{NA} and non-\code{NA} cells are considered} \item{directions}{integer. Which cells are considered adjacent? Should be 8 (Queen's case) or 4 (Rook's case)} \item{falseval}{numeric. The value to use for cells that are not a boundary and not \code{NA}} \item{filename}{character. Output filename} \item{...}{options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster. Cell values are either 1 (a border) or 0 (not a border), or \code{NA} } \seealso{ \code{\link{focal}}, \code{\link{patches}} } \examples{ r <- rast(nrows=18, ncols=36, xmin=0) r[150:250] <- 1 r[251:450] <- 2 bi <- boundaries(r) bo <- boundaries(r, inner=FALSE) bc <- boundaries(r, classes=TRUE) #plot(bc) } \keyword{methods} \keyword{spatial} terra/man/linearUnits.Rd0000644000175000017500000000174414201035750015063 0ustar nileshnilesh\name{linearUnits} \alias{linearUnits} \alias{linearUnits,SpatRaster-method} \alias{linearUnits,SpatVector-method} \title{Linear units of the coordinate reference system} \description{ Get the linear units of the coordinate reference system (crs) of a SpatRaster or SpatVector expressed in m. The value returned is used internally to transform area and perimenter measures to meters. The value returned for longitude/latitude crs is zero. } \usage{ \S4method{linearUnits}{SpatRaster}(x) \S4method{linearUnits}{SpatVector}(x) } \arguments{ \item{x}{SpatRaster or SpatVector} } \value{ numeric (meter) } \seealso{\code{\link{crs}}} \examples{ x <- rast() crs(x) <- "" linearUnits(x) crs(x) <- "+proj=longlat +datum=WGS84" linearUnits(x) crs(x) <- "+proj=utm +zone=1 +units=cm" linearUnits(x) crs(x) <- "+proj=utm +zone=1 +units=km" linearUnits(x) crs(x) <- "+proj=utm +zone=1 +units=us-ft" linearUnits(x) } \keyword{spatial} terra/man/coords.Rd0000644000175000017500000000275114201035750014056 0ustar nileshnilesh\name{crds} \docType{methods} \alias{crds} \alias{crds,SpatVector-method} \alias{crds,SpatRaster-method} \title{Get the coordinates of SpatVector geometries or SpatRaster cells} \description{ Get the coordinates of a SpatVector or SpatRaster cells. A matrix or data.frame of the x (longitude) and y (latitude) coordinates is returned. } \usage{ \S4method{crds}{SpatVector}(x, df=FALSE) \S4method{crds}{SpatRaster}(x, df=FALSE, na.rm=TRUE) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{df}{logical. If \code{TRUE} a \code{data.frame} is returned in stead of a matrix} \item{na.rm}{logical. If \code{TRUE} cells that are \code{NA} are excluded} } \value{ matrix or data.frame } \seealso{ \code{\link{geom}} returns the complete structure of SpatVector geometries. For SpatRaster see code{\link{xyFromCell}} } \examples{ x1 <- rbind(c(-175,-20), c(-140,55), c(10, 0), c(-140,-60)) x2 <- rbind(c(-125,0), c(0,60), c(40,5), c(15,-45)) x3 <- rbind(c(-10,0), c(140,60), c(160,0), c(140,-55)) x4 <- rbind(c(80,0), c(105,13), c(120,2), c(105,-13)) z <- rbind(cbind(object=1, part=1, x1), cbind(object=2, part=1, x2), cbind(object=3, part=1, x3), cbind(object=3, part=2, x4)) colnames(z)[3:4] <- c('x', 'y') z <- cbind(z, hole=0) z[(z[, "object"]==3 & z[,"part"]==2), "hole"] <- 1 p <- vect(z, "polygons") crds(p) f <- system.file("ex/lux.shp", package="terra") v <- vect(f) g <- crds(v) head(g) } \keyword{spatial} terra/man/autocor.Rd0000644000175000017500000000437414201035747014252 0ustar nileshnilesh\name{autocorrelation} \alias{autocor} \alias{autocor,numeric-method} \alias{autocor,SpatRaster-method} \title{Spatial autocorrelation} \description{ Compute spatial autocorrelation for a numeric vector or a SpatRaster. You can compute standard (global) Moran's I or Geary's C, or local indicators of spatial autocorrelation (Anselin, 1995). } \usage{ \S4method{autocor}{numeric}(x, w, method="moran") \S4method{autocor}{SpatRaster}(x, w=matrix(c(1,1,1,1,0,1,1,1,1),3), method="moran", global=TRUE) } \arguments{ \item{x}{numeric or SpatRaster} \item{w}{Spatial weights defined by or a rectangular matrix. For a SpatRaster this matrix must the sides must have an odd length (3, 5, ...)} \item{global}{logical. If \code{TRUE} global autocorrelation is computed instead of local autocorrelation} \item{method}{character. If \code{x} is numeric or SpatRaster: "moran" for Moran's I and "geary" for Geary's C. If \code{x} is numeric also: "Gi", "Gi*" (the Getis-Ord statistics), locmor (local Moran's I) and "mean" (local mean)} } \value{ numeric or SpatRaster } \details{ The default setting uses a 3x3 neighborhood to compute "Queen's case" indices. You can use a filter (weights matrix) to do other things, such as "Rook's case", or different lags. } \seealso{ The \code{spdep} package for additional and more general approaches for computing spatial autocorrelation } \references{ Moran, P.A.P., 1950. Notes on continuous stochastic phenomena. Biometrika 37:17-23 Geary, R.C., 1954. The contiguity ratio and statistical mapping. The Incorporated Statistician 5: 115-145 Anselin, L., 1995. Local indicators of spatial association-LISA. Geographical Analysis 27:93-115 \url{https://en.wikipedia.org/wiki/Indicators_of_spatial_association} } \examples{ ### raster r <- rast(nrows=10, ncols=10, xmin=0) values(r) <- 1:ncell(r) autocor(r) # rook's case neighbors f <- matrix(c(0,1,0,1,0,1,0,1,0), nrow=3) autocor(r, f) # local rc <- autocor(r, w=f, global=FALSE) ### numeric (for vector data) f <- system.file("ex/lux.shp", package="terra") v <- vect(f) w <- relate(v, relation="touches") # global autocor(v$AREA, w) # local v$Gi <- autocor(v$AREA, w, "Gi") plot(v, "Gi") } \keyword{spatial} terra/man/approximate.Rd0000644000175000017500000000635614201035747015131 0ustar nileshnilesh\name{approximate} \docType{methods} \alias{approximate} \alias{approximate,SpatRaster-method} \title{Estimate values for cell values that are \code{NA} by interpolating between layers} \description{ approximate uses the \code{stats} function \code{\link{approx}} to estimate values for cells that are \code{NA} by interpolation across layers. Layers are considered equidistant, unless argument \code{z} is used, or \code{time(x)} returns values that are not \code{NA}, in which case these values are used to determine distance between layers. For estimation based on neighboring cells see \code{\link{focal}} } \usage{ \S4method{approximate}{SpatRaster}(x, method="linear", yleft, yright, rule=1, f=0, ties=mean, z=NULL, NArule=1,filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{method}{specifies the interpolation method to be used. Choices are "linear" or "constant" (step function; see the example in \code{\link{approx}}} \item{yleft}{the value to be returned before a non-\code{NA} value is encountered. The default is defined by the value of rule given below} \item{yright}{the value to be returned after the last non-\code{NA} value is encountered. The default is defined by the value of rule given below} \item{rule}{an integer (of length 1 or 2) describing how interpolation is to take place at for the first and last cells (before or after any non-\code{NA} values are encountered). If rule is 1 then NAs are returned for such points and if it is 2, the value at the closest data extreme is used. Use, e.g., \code{rule = 2:1}, if the left and right side extrapolation should differ} \item{f}{for method = "constant" a number between 0 and 1 inclusive, indicating a compromise between left- and right-continuous step functions. If y0 and y1 are the values to the left and right of the point then the value is \code{y0*(1-f)+y1*f} so that \code{f = 0)} is right-continuous and \code{f = 1} is left-continuous} \item{ties}{Handling of tied 'z' values. Either a function with a single vector argument returning a single number result or the string "ordered"} \item{z}{numeric vector to indicate the distance between layers (e.g., depth). The default is \code{time(x)} if these are not \code{NA} or else \code{1:nlys(x)} } \item{NArule}{single integer used to determine what to do when only a single layer with a non-\code{NA} value is encountered (and linear interpolation is not possible). The default value of 1 indicates that all layers will get this value for that cell; all other values do not change the cell values} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{ \code{ \link{focal}}, \code{\link{fillTime}} } \examples{ r <- rast(ncols=5, nrows=5) r1 <- setValues(r, runif(ncell(r))) r2 <- setValues(r, runif(ncell(r))) r3 <- setValues(r, runif(ncell(r))) r4 <- setValues(r, runif(ncell(r))) r5 <- setValues(r, NA) r6 <- setValues(r, runif(ncell(r))) r1[6:10] <- NA r2[5:15] <- NA r3[8:25] <- NA s <- c(r1,r2,r3,r4,r5,r6) s[1:5] <- NA x1 <- approximate(s) x2 <- approximate(s, rule=2) x3 <- approximate(s, rule=2, z=c(1,2,3,5,14,15)) } \keyword{spatial} terra/man/contour.Rd0000644000175000017500000000275714201035750014264 0ustar nileshnilesh\name{contour} \docType{methods} \alias{contour} \alias{contour,SpatRaster-method} \alias{as.contour} \alias{as.contour,SpatRaster-method} \title{Contour plot} \description{ Contour lines of a SpatRaster. Use \code{add=TRUE} to add the lines to the current plot. See \code{\link[graphics]{contour}} for details. if \code{filled=TRUE}, a new filled contour plot is made. See \code{\link[graphics]{filled.contour}} for details. \code{as.contour} returns the contour lines as a SpatVector. } \usage{ \S4method{contour}{SpatRaster}(x, maxcells=100000, filled=FALSE, ...) \S4method{as.contour}{SpatRaster}(x, maxcells=100000, ...) } \arguments{ \item{x}{SpatRaster. Only the first layer is used} \item{maxcells}{maximum number of pixels used to create the contours} \item{filled}{logical. If \code{TRUE}, a \code{\link[graphics]{filled.contour}} plot is made} \item{...}{any argument that can be passed to \code{\link[graphics]{contour}} or \code{\link[graphics]{filled.contour}} (graphics package)} } \seealso{ \code{\link[terra]{plot}} } \examples{ r <- rast(system.file("ex/elev.tif", package="terra")) plot(r) contour(r, add=TRUE) v <- as.contour(r) plot(r) lines(v) contour(r, filled=TRUE, nlevels=5) ## if you want a SpatVector with contour lines template <- disagg(rast(r), 10) rr <- resample(r, template) rr <- floor(rr/100) * 100 v <- as.polygons(rr) plot(v, 1, col=terrain.colors(7)) } \keyword{methods} \keyword{spatial} terra/man/math-generics.Rd0000644000175000017500000000503214201035750015306 0ustar nileshnilesh\name{Math-methods} \docType{methods} \alias{Math-methods} \alias{Math2-methods} \alias{Math,SpatRaster-method} \alias{Math2,SpatRaster-method} \alias{Math,SpatExtent-method} \alias{Math2,SpatExtent-method} \alias{Math2,SpatVector-method} \alias{log} \alias{log,SpatRaster-method} \alias{round} \alias{round,SpatRaster-method} \alias{round} \alias{round,SpatVector-method} \alias{sqrt} \alias{sqrt,SpatRaster-method} \alias{math} \alias{math,SpatRaster-method} \title{General mathematical methods} \description{ Standard mathematical methods for computations with SpatRaster objects. Computations are local (applied on a cell by cell basis). If multiple SpatRaster objects are used, these must have the same extent and resolution. These have been implemented: \code{abs, sign, sqrt, ceiling, floor, trunc, cummax, cummin, cumprod, cumsum, log, log10, log2, log1p, acos, acosh, asin, asinh, atan, atanh, exp, expm1, cos, cosh, sin, sinh, tan, tanh, round, signif} Instead of directly calling these methods, you can also provide their name to the \code{math} method. This is useful if you want to provide an output filename. The following methods have been implemented for \code{SpatExtent}: \code{round, floor, ceiling} \code{round} has also been implemented for \code{SpatVector}, to round the coordinates of the geometries. } \usage{ \S4method{sqrt}{SpatRaster}(x) \S4method{log}{SpatRaster}(x, base=exp(1)) \S4method{round}{SpatRaster}(x, digits=0) \S4method{math}{SpatRaster}(x, fun, digits=0, filename="", overwrite=FALSE, ...) \S4method{round}{SpatVector}(x, digits=4) } \seealso{ See \code{\link{app}} to use mathematical functions not implemented by the package, and \code{\link{Arith-methods}} for arithmetical operations } \arguments{ \item{x}{SpatRaster} \item{base}{a positive or complex number: the base with respect to which logarithms are computed} \item{digits}{Number of digits for rounding} \item{fun}{character. Math function name} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster or SpatExtent } \examples{ r1 <- rast(ncols=10, nrows=10) v <- runif(ncell(r1)) v[10:20] <- NA values(r1) <- v r2 <- rast(r1) values(r2) <- 1:ncell(r2) / ncell(r2) r <- c(r1, r2) s <- sqrt(r) # same as math(r, "sqrt") round(s, 1) } \keyword{methods} \keyword{math} \keyword{spatial} terra/man/summarize-generics.Rd0000644000175000017500000000671114201035750016376 0ustar nileshnilesh\name{summarize} \docType{methods} \alias{Summary-methods} \alias{median} \alias{mean} \alias{min} \alias{max} \alias{which.min} \alias{which.max} \alias{any} \alias{all} \alias{prod} \alias{range} \alias{sum} \alias{mean,SpatRaster-method} \alias{mean,SpatVector-method} \alias{mean,SpatExtent-method} \alias{median,SpatRaster-method} \alias{median,SpatVector-method} \alias{min,SpatRaster-method} \alias{max,SpatRaster-method} \alias{range,SpatRaster-method} \alias{which.min,SpatRaster-method} \alias{which.max,SpatRaster-method} \alias{any,SpatRaster-method} \alias{all,SpatRaster-method} \alias{prod,SpatRaster-method} \alias{range,SpatRaster-method} \alias{sum,SpatRaster-method} \alias{stdev} \alias{stdev,SpatRaster-method} \title{Summarize} \description{ Compute summary statistics for cells, either across layers or between layers (parallel summary). The following summary methods are available for SpatRaster: \code{any, all, max, min, mean, median, prod, range, stdev, sum, which.min, which.max}. See \code{\link{modal}} to compute the mode and \code{\link{app}} to compute summary statistics that are not included here. Because generic functions are used, the method applied is chosen based on the first argument: "\code{x}". This means that if \code{r} is a SpatRaster, \code{mean(r, 5)} will work, but \code{mean(5, r)} will not work. The \code{mean} method has an argument "trim" that is ignored. If \code{pop=TRUE} \code{stdev} computes the population standard deviation, computed as: \code{f <- function(x) sqrt(sum((x-mean(x))^2) / length(x))} This is different than the sample standard deviation returned by \code{sd} (which uses \code{n-1} as denominator). } \usage{ \S4method{min}{SpatRaster}(x, ..., na.rm=FALSE) \S4method{max}{SpatRaster}(x, ..., na.rm=FALSE) \S4method{range}{SpatRaster}(x, ..., na.rm=FALSE) \S4method{prod}{SpatRaster}(x, ..., na.rm=FALSE) \S4method{sum}{SpatRaster}(x, ..., na.rm=FALSE) \S4method{any}{SpatRaster}(x, ..., na.rm=FALSE) \S4method{all}{SpatRaster}(x, ..., na.rm=FALSE) \S4method{range}{SpatRaster}(x, ..., na.rm=FALSE) \S4method{which.min}{SpatRaster}(x) \S4method{which.max}{SpatRaster}(x) \S4method{stdev}{SpatRaster}(x, ..., pop=TRUE, na.rm=FALSE) \S4method{mean}{SpatRaster}(x, ..., trim=NA, na.rm=FALSE) \S4method{median}{SpatRaster}(x, na.rm=FALSE, ...) } \arguments{ \item{x}{SpatRaster} \item{...}{additional SpatRaster objects or numeric values; and arguments \code{filename}, \code{overwrite} and \code{wopt} as for \code{\link{writeRaster}}} \item{na.rm}{logical. If \code{TRUE}, \code{NA} values are ignored. If \code{FALSE}, \code{NA} is returned if \code{x} has any \code{NA} values} \item{trim}{ignored} \item{pop}{logical. If \code{TRUE}, the population standard deviation is computed. Otherwise the sample standard deviation is computed} } \value{SpatRaster} \seealso{\code{\link{app}}, \code{\link{Math-methods}}, \code{\link{modal}}, \code{\link{which.lyr}} } \examples{ set.seed(0) r <- rast(nrows=10, ncols=10, nlyrs=3) values(r) <- runif(ncell(r) * nlyr(r)) x <- mean(r) # note how this returns one layer x <- sum(c(r, r[[2]]), 5) # and this returns three layers y <- sum(r, r[[2]], 5) max(r) max(r, 0.5) y <- stdev(r) # not the same as yy <- app(r, sd) z <- stdev(r, r*2) x <- mean(r, filename=paste0(tempfile(), ".tif")) } \keyword{methods} \keyword{spatial} terra/man/match.Rd0000644000175000017500000000225314201035750013656 0ustar nileshnilesh\name{match} \docType{methods} \alias{match} \alias{match,SpatRaster-method} \alias{\%in\%} \alias{\%in\%,SpatRaster-method} \title{Value matching for SpatRasters} \description{ \code{match} returns a SpatRaster with the position of the matched values. The cell values are the index of the table argument. \code{\%in\%} returns a 0/1 (FALSE/TRUE) SpatRaster indicating if the cells values were matched or not. } \usage{ match(x, table, nomatch = NA_integer_, incomparables = NULL) x \%in\% table } \arguments{ \item{x}{SpatRaster} \item{table}{vector of the values to be matched against} \item{nomatch}{the value to be returned in the case when no match is found. Note that it is coerced to integer} \item{incomparables}{a vector of values that cannot be matched. Any value in x matching a value in this vector is assigned the nomatch value. For historical reasons, FALSE is equivalent to NULL} } \value{ SpatRaster } \seealso{ \code{\link{app}, \link[base]{match}} } \examples{ r <- rast(nrows=10, ncols=10) values(r) <- 1:100 m <- match(r, c(5:10, 50:55)) n <- r \%in\% c(5:10, 50:55) } \keyword{spatial} \keyword{methods} terra/man/crop.Rd0000644000175000017500000000374514201035750013534 0ustar nileshnilesh\name{crop} \docType{methods} \alias{crop} \alias{crop,SpatRaster-method} \alias{crop,SpatRasterDataset-method} \alias{crop,SpatVector-method} \title{Cut out a geographic subset} \description{ Cut out a part of a SpatRaster with a SpatExtent, or another object from which an extent can be obtained. With a SpatRaster you can only extract rectangular areas, but see \code{\link{mask}} for setting cell values within SpatRaster to \code{NA}. You can crop a SpatVector with a rectangle, or with another vector (if these are not polygons, the minimum convex hull is used). Unlike with \code{\link{intersect}} the geometries and attributes of \code{y} are not transferred to the output. } \usage{ \S4method{crop}{SpatRaster}(x, y, snap="near", mask=FALSE, filename="", ...) \S4method{crop}{SpatRasterDataset}(x, y, snap="near", filename="", ...) \S4method{crop}{SpatVector}(x, y) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{y}{SpatRaster, SpatVector, SpatExtent or other object that has a SpatExtent (\code{\link{ext}} returns a \code{SpatExtent})} \item{snap}{character. One of "near", "in", or "out". Used to align \code{y} to the geometry of \code{x}} \item{mask}{logical. Should \code{y} be used to mask? Only used if \code{y} is a SpatVector} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{\code{intersect}} \examples{ r <- rast(xmin=0, xmax=10, ymin=0, ymax=10, nrows=25, ncols=25) values(r) <- 1:ncell(r) e <- ext(-5, 5, -5, 5) rc <- crop(r, e) # crop and mask f <- system.file("ex/elev.tif", package="terra") r <- rast(f) f <- system.file("ex/lux.shp", package="terra") v <- vect(f) cm <- crop(r, v[9:12,], mask=TRUE) plot(cm) lines(v) # crop vector f <- system.file("ex/lux.shp", package="terra") v <- vect(f) e <- ext(6.15, 6.3, 49.7, 49.8) x <- crop(v, e) plot(x, "NAME_1") } \keyword{spatial} terra/man/sample.Rd0000644000175000017500000001132314201035750014041 0ustar nileshnilesh\name{spatSample} \docType{methods} \alias{spatSample} \alias{spatSample,SpatRaster-method} \alias{spatSample,SpatExtent-method} \alias{spatSample,SpatVector-method} \title{Take a regular sample} \description{ Take a spatial sample from a SpatRaster, SpatVector or SpatExtent. Sampling a SpatVector or SpatExtent always returns a SpatVector of points. With a SpatRaster, you can get cell values, cell numbers (\code{cells=TRUE}), coordinates (\code{xy=TRUE}) or (when \code{type="regular"} and \code{as.raster=TRUE}) get a new SpatRaster with the same extent, but fewer cells. In order to assure regularity when requesting a regular sample, the number of cells or points returned may not be exactly the same as the \code{size} requested. } \usage{ \S4method{spatSample}{SpatRaster}(x, size, method="random", replace=FALSE, na.rm=FALSE, as.raster=FALSE, as.df=TRUE, as.points=FALSE, values=TRUE, cells=FALSE, xy=FALSE, ext=NULL, warn=TRUE, weights=NULL) \S4method{spatSample}{SpatVector}(x, size, method="random", strata=NULL, chess="") \S4method{spatSample}{SpatExtent}(x, size, method="random", lonlat, as.points=FALSE) } \arguments{ \item{x}{SpatRaster, SpatVector or SpatExtent} \item{size}{numeric. The sample size. If \code{x} is a SpatVector, you can also provide a vector of the same length as \code{x} in wich case sampling is done seperately for each geometry. If \code{x} is a SpatRaster, and you are using \code{method="regular"} you can specify the size as two numbers (number of rows and columns)} \item{method}{character. Should be "regular" or "random", If \code{x} is a \code{SpatRaster}, it can also be "stratified" (each value in \code{x} is a stratum) or "weights" (each value in \code{x} is a probability weight)} \item{replace}{logical. If \code{TRUE}, sampling is with replacement (if \code{method="random"}} \item{na.rm}{logical. If \code{TRUE}, code{NAs} are removed. Only used with random sampling of cell values. That is with \code{method="random", as.raster=FALSE, cells=FALSE}} \item{as.raster}{logical. If \code{TRUE}, a SpatRaster is returned} \item{as.df}{logical. If \code{TRUE}, a data.frame is returned instead of a matrix} \item{as.points}{logical. If \code{TRUE}, a SpatVector of points is returned} \item{values}{logical. If \code{TRUE} cell values are returned} \item{cells}{logical. If \code{TRUE}, cell numbers are returned. If \code{method="stratified"} this is always set to \code{TRUE} if \code{xy=FALSE}} \item{xy}{logical. If \code{TRUE}, cell coordinates are returned} \item{ext}{SpatExtent or NULL to restrict sampling to a a subset of the area of \code{x}} \item{warn}{logical. Give a warning if the sample size returned is smaller than requested} \item{weights}{SpatRaster. Used to provide weights when \code{method="stratified"}} \item{strata}{if not NULL, stratified random sampling is done, taking \code{size} samples from each stratum. If \code{x} has polygon geometry, \code{strata} must be a field name (or index) in \code{x}. If \code{x} has point geometry, \code{strata} can be a SpatVector of polygons or a SpatRaster} \item{chess}{character. One of "", "white", or "black". For stratified sampling if \code{strata} is a SpatRaster. If not "", samples are only taken from alternate cells, organized like the "white" or "black" fields on a chessboard} \item{lonlat}{logical. If \code{TRUE}, sampling of a SpatExtent is weighted by \code{cos(latitude)}. For SpatRaster and SpatVector this done based on the \code{\link{crs}}, but it is ignored if \code{as.raster=TRUE}} } \value{ numeric matrix, data.frame, SpatRaster or SpatVector } \examples{ f <- system.file("ex/elev.tif", package="terra") r <- rast(f) s <- spatSample(r, 10, as.raster=TRUE) spatSample(r, 10) spatSample(r, 10, "random") ## if you require cell numbers and/or coordinates size <- 6 # random cells cells <- spatSample(r, 6, "random", cells=TRUE, values=FALSE) cells <- as.vector(cells) v <- r[cells] xy <- xyFromCell(r, cells) cbind(xy, v) # regular cells <- spatSample(r, 6, "regular", cells=TRUE, values=FALSE) cells <- as.vector(cells) v <- r[cells] xy <- xyFromCell(r, cells) cbind(xy, v) # stratified rr <- rast(ncol=10, nrow=10, names="stratum") set.seed(1) values(rr) <- round(runif(ncell(rr), 1, 3)) spatSample(rr, 2, "stratified", xy=TRUE) s <- spatSample(rr, 5, "stratified", as.points=TRUE) plot(rr, plg=list(title="raster")) plot(s, 1, add=TRUE, plg=list(x=185, y=1, title="points")) ## SpatExtent e <- ext(r) spatSample(e, 10, "random", lonlat=TRUE) ## SpatVector f <- system.file("ex/lux.shp", package="terra") v <- vect(f) #sample geometries i <- sample(nrow(v), 5) vv <- v[i,] } \keyword{spatial} terra/man/activeCat.Rd0000644000175000017500000000172314201035747014474 0ustar nileshnilesh\name{activeCat} \docType{methods} \alias{activeCat} \alias{activeCat,SpatRaster-method} \alias{activeCat<-} \alias{activeCat<-,SpatRaster-method} \title{Active category} \description{ Get or set the active category of a multi-categorical SpatRaster layer } \usage{ \S4method{activeCat}{SpatRaster}(x, layer=1) \S4method{activeCat}{SpatRaster}(x, layer=1)<-value } \arguments{ \item{x}{SpatRaster} \item{layer}{positive integer, the layer number or name} \item{value}{a data.frame (ID, category) or vector with category names} } \value{ integer } \seealso{\code{\link{catalyze}}, \code{\link{cats}}} \examples{ set.seed(0) r <- rast(nrows=10, ncols=10) values(r) <- sample(3, ncell(r), replace=TRUE) + 10 d <- data.frame(id=11:13, cover=c("forest", "water", "urban"), letters=letters[1:3], value=10:12) levels(r) <- d activeCat(r) activeCat(r) <- 3 activeCat(r) } \keyword{methods} \keyword{spatial} terra/man/north.Rd0000644000175000017500000000357314201035750013722 0ustar nileshnilesh\name{north} \alias{arrow} \alias{north} \title{North arrow} \description{ Add a (North) arrow to a map } \usage{ north(xy=NULL, type=1, label="N", angle=0, d, head=0.1, xpd=TRUE, ...) arrow(...) } \arguments{ \item{xy}{numeric. x and y coordinate to place the arrow. It can also be one of following character values: "bottomleft", "bottom", "bottomright", topleft", "top", "topright", "left", "right", or NULL} \item{type}{integer between 1 and 12, or a character (unicode) representation of a right pointing arrow such as \code{"\u27A9"}} \item{label}{character, to be printed near the arrow} \item{angle}{numeric. The angle of the arrow in degrees} \item{d}{numeric. Distance covered by the arrow in plot coordinates. Only applies to \code{type=1}} \item{head}{numeric. The size of the arrow "head", for \code{type=1}} \item{xpd}{logical. If \code{TRUE}, the scale bar or arrow can be outside the plot area} \item{...}{graphical arguments to be passed to other methods } } \value{ none } \seealso{ \code{\link[terra]{sbar}}, \code{\link[terra]{plot}}, \code{\link[terra]{inset}} } \examples{ f <- system.file("ex/meuse.tif", package="terra") r <- rast(f) plot(r) north() north(c(178550, 332500), d=250) \dontrun{ f <- system.file("ex/elev.tif", package="terra") r <- rast(f) plot(r, type="interval") sbar(15, c(6.3, 50), type="bar", below="km", label=c(0,7.5,15), cex=.8) north(type=3, cex=.8) north(xy=c(6.7, 49.9), type=2, angle=45, label="NE") north(xy=c(6.6, 49.7), type=5, cex=1.25) north(xy=c(5.5, 49.6), type=9) north(d=.05, xy=c(5.5, 50), angle=180, label="S", lwd=2, col="blue") ## all arrows r <- rast(res=10) values(r) <- 1 plot(r, col="white", axes=FALSE, legend=FALSE, mar=c(0,0,0,0), reset=TRUE) for (i in 1:12) { x = -200+i*30 north(xy=cbind(x,30), type=i) text(x, -20, i, xpd=TRUE) } } } \keyword{spatial} terra/man/split.Rd0000644000175000017500000000141214201035750013711 0ustar nileshnilesh\name{split} \docType{methods} \alias{split} \alias{split,SpatRaster-method} \alias{split,SpatVector-method} \title{Split} \description{ Split a SpatVector or SpatRaster} \usage{ \S4method{split}{SpatRaster}(x, f) \S4method{split}{SpatVector}(x, f) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{f}{If \code{x} is a SpatVector: a field (variable) name or a vector of the same length as \code{x}. If \code{x} is a SpatRaster: a vector of the length \code{nlyr(x)}} } \value{ Same as \code{x} } \examples{ v <- vect(system.file("ex/lux.shp", package="terra")) x <- split(v, "NAME_1") s <- rast(system.file("ex/logo.tif", package="terra")) y <- split(s, c(1,2,1)) sds(y) } \keyword{methods} \keyword{spatial} terra/man/focalValues.Rd0000644000175000017500000000167614201035750015036 0ustar nileshnilesh\name{focalValues} \docType{methods} \alias{focalValues} \alias{focalValues,SpatRaster-method} \title{Get focal values} \description{ Get a matrix in which each row had the focal values of a cell. These are the values of a cell and a rectangular window around it. } \usage{ \S4method{focalValues}{SpatRaster}(x, w=3, row=1, nrows=nrow(x), fill=NA) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{w}{window. The window can be defined as one (for a square) or two odd numbers (row, col); or with an odd sized matrix} \item{row}{positive integer. Row number to start from, should be between 1 and nrow(x)} \item{nrows}{positive integer. How many rows?} \item{fill}{numeric used as values for imaginary cells outside the raster} } \value{ matrix } \examples{ r <- rast(ncol=4, nrow=4, crs="+proj=utm +zone=1 +datum=WGS84") values(r) <- 1:ncell(r) focalValues(r) } \keyword{spatial} \keyword{methods} terra/man/lapp.Rd0000644000175000017500000000721314201035750013517 0ustar nileshnilesh\name{lapp} \docType{methods} \alias{lapp} \alias{lapp,SpatRaster-method} \alias{lapp,SpatRasterDataset-method} \title{Apply a function to layers of a SpatRaster, or sub-datasets of a SpatRasterDataset} \description{ Apply a function to a SpatRaster, using layers as arguments. The number of arguments in function \code{fun} must match the number of layers in the SpatRaster (or the number of sub-datasets in the SpatRasterDataset). For example, if you want to multiply two layers, you could use this function: \code{fun=function(x,y){return(x*y)}} percentage: \code{fun=function(x,y){return(100 * x / y)}}. If you combine three layers you could use \code{fun=function(x,y,z){return((x + y) * z)}} Before you use the function, test it to make sure that it is vectorized. That is, it should work for vectors longer than one, not only for single numbers. The function must return the same number of elements as its input vectors, or multiples of that. Also make sure that the function is NA-proof: it should returns the same number of values when some or all input values are \code{NA}. And the function must return a vector or a matrix, not a \code{data.frame}. Use \code{\link{app}} for summarize functions such as \code{sum}, that take any number of arguments; and \code{\link{tapp}} to do so for groups of layers. } \usage{ \S4method{lapp}{SpatRaster}(x, fun, ..., usenames=FALSE, cores=1, filename="", overwrite=FALSE, wopt=list()) \S4method{lapp}{SpatRasterDataset}(x, fun, ..., recycle=FALSE, filename="", overwrite=FALSE, wopt=list()) } \arguments{ \item{x}{SpatRaster or SpatRasterDataset} \item{fun}{a function that takes a vector and can be applied to each cell of \code{x}} \item{...}{additional arguments to be passed to \code{fun}} \item{usenames}{logical. Use the layer names to match the function arguments? If \code{FALSE} matching is by position} \item{cores}{positive integer. If \code{cores > 1}, a 'parallel' package cluster with that many cores is created and used. You can also supply a cluster object} \item{recycle}{logical. Recycle layers to match the subdataset with the largest number of layers} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{list with named options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{\code{ \link{app}, \link[terra]{tapp}, \link[terra]{math}} } \note{ Use \code{\link{sapp}} or \code{lapply} to apply a function that takes a SpatRaster as argument to each layer of a SpatRaster (that is rarely necessary). } \examples{ s <- rast(system.file("ex/logo.tif", package="terra")) + 1 ss <- s[[2:1]] fvi <- function(x, y){ (x - y ) / (x + y) } x <- lapp(ss, fun=fvi ) # which is the same as supplying the layers to "fun" # in some cases this will be much faster y <- fvi(s[[2]], s[[1]]) f2 <- function(x, y, z){ (z - y + 1) / (x + y + 1) } p1 <- lapp(s, fun=f2 ) p2 <- lapp(s[[1:2]], f2, z=200) # the usenames argument fvi2 <- function(red, green){ (red - green ) / (red + green) } names(s) x1 <- lapp(s[[1:2]], fvi2, usenames=TRUE) x2 <- lapp(s[[2:1]], fvi2, usenames=TRUE) # x1 and x2 are the same, despite the change in the order of the layers # x4 is also the same, but x3 is not x3 <- lapp(s[[2:1]], fvi2, usenames=FALSE) x4 <- lapp(s, fvi2, usenames=TRUE) # while this would fail because # there are too many layers in s # x5 <- lapp(s, fvi2, usenames=FALSE) pairs(c(x1, x2, x3, x4)) ## SpatRasterDataset x <- sds(s, s[[1]]+50) lapp(x, function(x, y) x/y, recycle=TRUE) } \keyword{methods} \keyword{spatial} terra/man/densify.Rd0000644000175000017500000000256714201035750014233 0ustar nileshnilesh\name{densify} \docType{methods} \alias{densify} \alias{densify,SpatVector-method} \title{ Add additional nodes to lines or polygons } \description{ Add additional nodes to lines or polygons. This can be useful to do prior to using \code{project} such that the path does not change too much. } \usage{ \S4method{densify}{SpatVector}(x, interval, equalize=TRUE) } \arguments{ \item{x}{SpatVector} \item{interval}{numeric larger than 1, specifying the desired minimum interval between nodes} \item{equalize}{logical. If \code{TRUE}, new nodes are spread at equal intervals between old nodes} } \value{ SpatVector } \examples{ v <- vect(rbind(c(-120,-20), c(-80,5), c(-40,-60), c(-120,-20)), type="polygons", crs="+proj=longlat") vd <- densify(v, 200000) p <- project(v, "+proj=robin") pd <- project(vd, "+proj=robin") # good plot(pd, col="gray", border="red", lwd=10) points(pd, col="gray") # bad lines(p, col="blue", lwd=3) points(p, col="blue", cex=2) plot(p, col="blue", alpha=.1, add=TRUE) legend("topright", c("good", "bad"), col=c("red", "blue"), lty=1, lwd=3) ## the other way around does not work ## unless the original data was truly planar (e.g. derived from a map) x <- densify(p, 250000) y <- project(x, "+proj=longlat") # bad plot(y) # good lines(vd, col="red") } \keyword{methods} \keyword{spatial} terra/man/factors.Rd0000644000175000017500000000604614201035750014227 0ustar nileshnilesh\name{factors} \docType{methods} \alias{is.factor} \alias{is.factor,SpatRaster-method} \alias{as.factor} \alias{as.factor,SpatRaster-method} \alias{levels} \alias{levels,SpatRaster-method} \alias{levels<-} \alias{levels<-,SpatRaster-method} \alias{cats} \alias{cats,SpatRaster-method} \alias{setCats} \alias{setCats,SpatRaster-method} \alias{categories} \alias{categories,SpatRaster-method} \title{Categorical rasters} \description{ A SpatRaster layer can be a categorical variable (factor). Like \code{\link{factor}}s, categories are stored as indices (integers) that have an associated label. For a SpatRaster, the index starts at 0, and cannot exceed 255. The categories can be inspected with \code{levels} and \code{cats}. With \code{levels<-} you can set the categories of the first layer by providing a vector of labels (the first value will be for cells with value 0, the second for 1, etc). You can also provide a \code{data.frame} that must have two or more columns, the first one identifying the cell values and the other column(s) providing the category labels. To set categories for multiple layers you can provide \code{levels<-} with a list with one element for each layer. With \code{categories} you can set it for any layer and you can also set the "active" category if there are multiple categories. } \usage{ \S4method{is.factor}{SpatRaster}(x) \S4method{levels}{SpatRaster}(x) \S4method{levels}{SpatRaster}(x)<-value \S4method{cats}{SpatRaster}(x, layer) \S4method{categories}{SpatRaster}(x, layer=1, value, index) } \arguments{ \item{x}{SpatRaster} \item{layer}{positive integer, the layer number or name} \item{value}{a data.frame (ID, category) or vector with category names} \item{index}{positive integer, indicating the column in \code{data.frame} \code{value} to be used as the (active) category, (not counting the first column with the cell values)} } \value{ list (levels, cats) or data.frame (cats for a single layer); logical (is.factor, setCats) } \seealso{\code{\link{activeCat}}, \code{\link{catalyze}}} \examples{ set.seed(0) r <- rast(nrows=10, ncols=10) values(r) <- sample(3, ncell(r), replace=TRUE) is.factor(r) cls <- c("forest", "water", "urban") # make the raster start at zero x <- r - 1 levels(x) <- cls names(x) <- "land cover" is.factor(x) x plot(x, col=c("green", "blue", "light gray")) text(x, digits=3, cex=.75, halo=TRUE) # raster starts at 3 x <- r + 2 is.factor(x) # approach 1 levels(x) <- c("", "", "", "forest", "water", "urban") # approach 2, also showing the use of two categories d <- data.frame(id=3:5, cover=cls, letters=letters[1:3], value=10:12) levels(x) <- d x ## switch categories cats(x, 1) # get current index activeCat(x) # set index activeCat(x) <- 3 plot(x, col=c("green", "blue", "light gray")) text(x, digits=3, cex=.75, halo=TRUE) r <- as.numeric(x) r activeCat(x) <- 2 p <- as.polygons(x) plot(p, "letters", col=c("green", "blue", "light gray")) } \keyword{methods} \keyword{spatial} terra/man/deepcopy.Rd0000644000175000017500000000172414201035750014374 0ustar nileshnilesh\name{deepcopy} \docType{methods} \alias{deepcopy} \alias{deepcopy,SpatRaster-method} \alias{deepcopy,SpatVector-method} \title{Deep copy} \description{ Make a deep copy of a SpatRaster or SpatVector. This is occasionally useful when wanting to use a replacement function in a shallow copy. That is a copy that was created like this: \code{x <- y}. If you use a replacement function to change an object, its shallow copies also change. } \usage{ \S4method{deepcopy}{SpatRaster}(x) \S4method{deepcopy}{SpatVector}(x) } \arguments{ \item{x}{SpatRaster or SpatVector} } \value{ Same as \code{x} } \examples{ r <- rast(ncols=10, nrows=10, nl=3) tm <- as.Date("2001-05-03") + 1:3 time(r) <- tm time(r) x <- r time(x) <- tm + 365 time(x) time(r) y <- deepcopy(r) time(y) <- tm - 365 time(y) time(r) # or make a new object like this z <- rast(r) time(z) <- tm time(z) time(r) } \keyword{methods} \keyword{spatial} terra/man/shade.Rd0000644000175000017500000000277514201035750013657 0ustar nileshnilesh\name{shade} \alias{shade} \title{Hill shading} \description{ Compute hill shade from slope and aspect layers (both in radians). Slope and aspect can be computed with function \code{\link{terrain}}. A hill shade layer is often used as a backdrop on top of which another, semi-transparent, layer is drawn. } \usage{ shade(slope, aspect, angle=45, direction=0, normalize=FALSE, filename="", ...) } \arguments{ \item{slope}{SpatRasterwith slope values (in radians) } \item{aspect}{SpatRaster with aspect values (in radians) } \item{angle}{ The the elevation angle of the light source (sun), in degrees} \item{direction}{ The direction (azimuth) angle of the light source (sun), in degrees} \item{normalize}{Logical. If \code{TRUE}, values below zero are set to zero and the results are multiplied with 255} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \seealso{ \code{\link{terrain}} } \references{ Horn, B.K.P., 1981. Hill shading and the reflectance map. Proceedings of the IEEE 69(1):14-47 } \examples{ f <- system.file("ex/elev.tif", package="terra") r <- rast(f) alt <- disagg(r, 10, method="bilinear") slope <- terrain(alt, "slope", unit="radians") aspect <- terrain(alt, "aspect", unit="radians") hill <- shade(slope, aspect, 40, 270) plot(hill, col=grey(0:100/100), legend=FALSE, mar=c(2,2,1,4)) plot(alt, col=rainbow(25, alpha=0.35), add=TRUE) } \keyword{spatial} terra/man/union.Rd0000644000175000017500000000411514201035750013711 0ustar nileshnilesh\name{union} \docType{methods} \alias{union} \alias{union,SpatExtent,SpatExtent-method} \alias{union,SpatVector,SpatVector-method} \alias{union,SpatVector,SpatExtent-method} \alias{union,SpatVector,missing-method} \title{ Union SpatVector or SpatExtent objects } \description{ Overlapping polygons (between, not within, objects) are intersected. Union for lines and points simply combines the two data sets; without any geometric intersections. This is equivalent to \code{\link{c}}. Attributes are joined. See \code{\link{c}} if you want to combine polygons without intersection. If code{x} and \code{y} have a different geometry type, a SpatVectorCollection is returned. If a single SpatVector is supplied, overlapping polygons are intersected. Original attributes are lost. New attributes allow for determining how many, and which, polygons overlapped. SpatExtent: Objects are combined into their union; this is equivalent to \code{+}. } \usage{ \S4method{union}{SpatVector,SpatVector}(x, y) \S4method{union}{SpatVector,missing}(x, y) \S4method{union}{SpatExtent,SpatExtent}(x, y) } \arguments{ \item{x}{SpatVector or SpatExtent} \item{y}{Same as \code{x} or missing} } \value{ SpatVector or SpatExtent } \seealso{ \code{\link[terra]{intersect}}) \code{\link{merge}} and \code{\link{mosaic}} to union SpatRaster objects. \code{\link{crop}} and \code{\link{extend}} for the union of SpatRaster and SpatExtent. \code{\link[terra]{merge}} for merging a data.frame with attributes of a SpatVector. } \examples{ e1 <- ext(-10, 10, -20, 20) e2 <- ext(0, 20, -40, 5) union(e1, e2) #SpatVector v <- vect(system.file("ex/lux.shp", package="terra")) v <- v[,3:4] p <- vect(c("POLYGON ((5.8 49.8, 6 49.9, 6.15 49.8, 6 49.65, 5.8 49.8))", "POLYGON ((6.3 49.9, 6.2 49.7, 6.3 49.6, 6.5 49.8, 6.3 49.9))"), crs=crs(v)) values(p) <- data.frame(pid=1:2, value=expanse(p)) u <- union(v, p) plot(u, "pid") b <- buffer(v, 1000) u <- union(b) u$sum <- rowSums(as.data.frame(u)) plot(u, "sum") } \keyword{methods} \keyword{spatial} terra/man/symdif.Rd0000644000175000017500000000111514201035750014051 0ustar nileshnilesh\name{symdif} \docType{methods} \alias{symdif} \alias{symdif,SpatVector,SpatVector-method} \title{ Symetrical difference } \description{ Symetrical difference of polygons } \usage{ \S4method{symdif}{SpatVector,SpatVector}(x, y) } \arguments{ \item{x}{SpatVector} \item{y}{SpatVector} } \value{ SpatVector } \seealso{ \code{\link{erase}} } \examples{ p <- vect(system.file("ex/lux.shp", package="terra")) b <- as.polygons(ext(6, 6.4, 49.75, 50)) #sd <- symdif(p, b) #plot(sd, col=rainbow(12)) } \keyword{methods} \keyword{spatial} terra/man/modal.Rd0000644000175000017500000000216014201035750013653 0ustar nileshnilesh\name{modal} \alias{modal} \alias{modal,SpatRaster-method} \title{modal value} \description{ Compute the mode for each cell across the layers of a SpatRaster. The mode, or modal value, is the most frequent value in a set of values. } \usage{ \S4method{modal}{SpatRaster}(x, ..., ties="first", na.rm=FALSE, filename="", overwrite=FALSE, wopt=list()) } \arguments{ \item{x}{SpatRaster} \item{...}{additional argument of the same type as \code{x} or numeric} \item{ties}{character. Indicates how to treat ties. Either "random", "lowest", "highest", "first", or "NA"} \item{na.rm}{logical. If \code{TRUE}, \code{NA} values are ignored. If \code{FALSE}, \code{NA} is returned if \code{x} has any \code{NA} values} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{list with named options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \examples{ r <- rast(system.file("ex/logo.tif", package="terra")) r <- c(r/2, r, r*2) m <- modal(r) } \keyword{univar} \keyword{math} terra/man/minmax.Rd0000644000175000017500000000206714201035750014056 0ustar nileshnilesh\name{extremes} \alias{minmax} \alias{hasMinMax} \alias{setMinMax} \alias{minmax,SpatRaster-method} \alias{hasMinMax,SpatRaster-method} \alias{setMinMax,SpatRaster-method} \title{Get or compute the minimum and maximum cell values} \description{ The minimum and maximum value of a SpatRaster are returned or computed (from a file on disk if necessary) and stored in the object. } \usage{ \S4method{minmax}{SpatRaster}(x) \S4method{hasMinMax}{SpatRaster}(x) \S4method{setMinMax}{SpatRaster}(x, force=FALSE) } \arguments{ \item{x}{ SpatRaster } \item{force}{logical. If \code{TRUE} min and max values are recomputed even if already avaialbe } } \value{ minmax: numeric matrix of minimum and maximum cell values by layer hasMinMax: logical indicating whether the min and max values are available. setMinMax: nothing. Used for the side-effect of computing the minimum and maximum values of a SpatRaster } \examples{ r <- rast(system.file("ex/elev.tif", package="terra")) minmax(r) } \keyword{ spatial } \keyword{ methods } terra/man/SpatVector-class.Rd0000644000175000017500000000114314201035747015762 0ustar nileshnilesh\name{SpatVector-class} \docType{class} \alias{SpatVector} \alias{SpatVector-class} \alias{Rcpp_SpatVector-class} \alias{PackedSpatVector-class} \alias{show,SpatVector-method} \title{Class "SpatVector" } \description{ Objects of class SpatVector. } \section{Objects from the Class}{ You can use the \code{\link{vect}} method to create SpatVector objects. } \section{Slots}{ \describe{ \item{\code{ptr}:}{pointer to the C++ class} } } \section{Methods}{ \describe{ \item{show}{display values of a SpatVector} } } \keyword{classes} \keyword{spatial} terra/man/ifelse.Rd0000644000175000017500000000251014201035750014025 0ustar nileshnilesh\name{ifel} \alias{ifel} \alias{ifel,SpatRaster-method} \title{ifelse for SpatRasters} \description{ Implementation of \code{\link[base]{ifelse}} for SpatRasters. This method allows for a concise expression of what can otherwise be achieved with a combination of \code{\link{classify}}, \code{\link{mask}}, and \code{\link{cover}}. \code{ifel} is an \code{R} equivalent to the \code{Con} method in ArcGIS (arcpy). } \usage{ \S4method{ifel}{SpatRaster}(test, yes, no, filename="", ...) } \arguments{ \item{test}{SpatRaster} \item{yes}{SpatRaster or numeric} \item{no}{SpatRaster or numeric} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \examples{ r <- rast(nrows=5, ncols=5, xmin=0, xmax=1, ymin=0, ymax=1) values(r) <- c(-10:0, NA, NA, NA, 0:10) x <- ifel(r > 1, 1, r) # same as a <- classify(r, cbind(1, Inf, 1)) # or b <- app(r, fun=function(i) {i[i > 1] <- 1; i}) # or d <- clamp(r, -Inf, 1) # or (not recommended for large datasets) e <- r e[e>1] <- 1 ## other examples f <- ifel(is.na(r), 100, r) z <- ifel(r > -2 & r < 2, 100, 0) # nested expressions y <- ifel(r > 1, 1, ifel(r < -1, -1, r)) k <- ifel(r > 0, r+10, ifel(r < 0, r-10, 3)) } \keyword{spatial} terra/man/tapp.Rd0000644000175000017500000000514714201035750013533 0ustar nileshnilesh\name{tapp} \docType{methods} \alias{tapp} \alias{tapp,SpatRaster-method} \title{Apply a function to subsets of layers of a SpatRaster} \description{ Apply a function to subsets of layers of a SpatRaster (similar to \code{\link[base]{tapply}} and \code{\link[stats]{aggregate}}). The layers are combined based on the \code{index}. The function used should return a single value, and the number of layers in the output SpatRaster equals the number of unique values in \code{index}. For example, if you have a SpatRaster with 6 layers, you can use \code{index=c(1,1,1,2,2,2)} and \code{fun=sum}. This will return a SpatRaster with two layers. The first layer is the sum of the first three layers in the input SpatRaster, and the second layer is the sum of the last three layers in the input SpatRaster. Indices are recycled such that \code{index=c(1,2)} would also return a SpatRaster with two layers (one based on the odd layers (1,3,5), the other based on the even layers (2,4,6)). See \code{\link{app}} or \code{\link{Summary-methods}} if you want to use a more efficient function that returns multiple layers based on \bold{all} layers in the SpatRaster object. } \usage{ \S4method{tapp}{SpatRaster}(x, index, fun, ..., cores=1, filename="", overwrite=FALSE, wopt=list()) } \arguments{ \item{x}{SpatRaster} \item{index}{factor or numeric (integer). Vector of length \code{nlyr(x)} (shorter vectors are recycled) grouping the input layers} \item{fun}{function to be applied. The following functions have been re-implemented in C++ for speed: "sum", "mean", "median", "modal", "which", "which.min", "which.max", "min", "max", "prod", "any", "all", "sd", "std", "first". To use the base-R function for say, "min", you could use something like \code{fun = \(i) min(i)}} \item{...}{additional arguments passed to \code{fun}} \item{cores}{positive integer. If \code{cores > 1}, a 'parallel' package cluster with that many cores is created and used. You can also supply a cluster object. Ignored for functions that are implemented by terra in C++ (see under fun)} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{list with named options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{\code{\link{app}}, \code{\link{Summary-methods}}} \examples{ r <- rast(ncols=10, nrows=10) values(r) <- 1:ncell(r) s <- c(r, r, r, r, r, r) s <- s * 1:6 b1 <- tapp(s, index=c(1,1,1,2,2,2), fun=sum) b1 b2 <- tapp(s, c(1,2,3,1,2,3), fun=sum) b2 } \keyword{methods} \keyword{spatial} terra/man/hist.Rd0000644000175000017500000000257514201035750013540 0ustar nileshnilesh\name{hist} \docType{methods} \alias{hist} \alias{hist,SpatRaster-method} \title{Histogram} \description{ Create a histogram of the values of a SpatRaster. For large datasets a sample of \code{maxcell} is used. } \usage{ \S4method{hist}{SpatRaster}(x, layer, maxcell=1000000, plot=TRUE, main, ...) } \arguments{ \item{x}{SpatRaster} \item{layer}{integer (or character) to indicate layer number (or name). Can be used to subset the layers to plot in a multilayer SpatRaster} \item{maxcell}{integer. To regularly sample very large objects} \item{plot}{logical. Plot the histogram or only return the histogram values} \item{main}{character. Main title(s) for the plot. Default is the value of \code{\link{names}}} \item{...}{additional arguments. See \code{\link[graphics]{hist}}} } \value{ This function is principally used for plotting a histogram, but it also returns an object of class "histogram" (invisibly if \code{plot=TRUE}). } \seealso{ \code{\link{pairs}, \link{boxplot}} } \examples{ r1 <- r2 <- rast(nrows=50, ncols=50) values(r1) <- runif(ncell(r1)) values(r2) <- runif(ncell(r1)) rs <- r1 + r2 rp <- r1 * r2 opar <- par(no.readonly =TRUE) par(mfrow=c(2,2)) plot(rs, main='sum') plot(rp, main='product') hist(rs) a <- hist(rp) a x <- c(rs, rp, sqrt(rs)) hist(x) par(opar) } \keyword{methods} \keyword{spatial} terra/man/pairs.Rd0000644000175000017500000000215714201035750013703 0ustar nileshnilesh\name{pairs} \docType{methods} \alias{pairs} \alias{pairs,SpatRaster-method} \title{ Pairs plot (matrix of scatterplots) } \description{ Pair plots of layers in a SpatRaster. This is a wrapper around graphics function \code{\link[graphics]{pairs}}. } \usage{ \S4method{pairs}{SpatRaster}(x, hist=TRUE, cor=TRUE, use="pairwise.complete.obs", maxcells=100000, ...) } \arguments{ \item{x}{SpatRaster} \item{hist}{logical. If TRUE a histogram of the values is shown on the diagonal} \item{cor}{logical. If TRUE the correlation coefficient is shown in the upper panels} \item{use}{argument passed to the \code{\link[stats]{cor}} function} \item{maxcells}{integer. Number of pixels to sample from each layer of a large SpatRaster} \item{...}{additional arguments (graphical parameters)} } \seealso{ \code{\link{boxplot}, \link{hist}} } \examples{ r <-rast(system.file("ex/elev.tif", package="terra")) s <- c(r, 1/r, sqrt(r)) names(s) <- c("elevation", "inverse", "sqrt") pairs(s) # to make indvidual histograms: hist(r) # or scatter plots: plot(s[[1]], s[[2]]) } \keyword{spatial} terra/man/resample.Rd0000644000175000017500000000433514201262202014367 0ustar nileshnilesh\name{resample} \alias{resample} \alias{resample,SpatRaster,SpatRaster-method} \title{Transfer values of a SpatRaster to another one with a different geometry} \description{ resample transfers values between SpatRaster objects that do not align (have a different origin and/or resolution). See \code{\link{project}} to change the coordinate reference system (crs). If the origin and crs are the same, you should consider using these other functions instead: \code{\link{aggregate}}, \code{\link{disagg}}, \code{\link{extend}} or \code{\link{crop}}. } \usage{ \S4method{resample}{SpatRaster,SpatRaster}(x, y, method, filename="", ...) } \arguments{ \item{x}{SpatRaster to be resampled} \item{y}{SpatRaster with the geometry that \code{x} should be resampled to} \item{method}{character. Method used for estimating the new cell values. One of: \code{near}: nearest neighbor. This method is fast, and it can be the preferred method if the cell values represent classes. It is not a good choice for continuous values. This is used by default if the first layer of \code{x} is categorical. \code{bilinear}: bilinear interpolation. This is the default if the first layer of \code{x} is numeric (not categorical). \code{cubic}: cubic interpolation. \code{cubicspline}: cubic spline interpolation. \code{lanczos}: Lanczos windowed sinc resampling. \code{sum}: the weighted sum of all non-NA contributing grid cells. \code{min, q1, med, q3, max, average, mode, rms}: the minimum, first quartile, median, third quartile, maximum, mean, mode, or root-mean-square value of all non-NA contributing grid cells. } \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{ \code{\link{aggregate}}, \code{\link{disagg}}, \code{\link{crop}}, \code{\link{project}}, } \examples{ r <- rast(nrows=3, ncols=3, xmin=0, xmax=10, ymin=0, ymax=10) values(r) <- 1:ncell(r) s <- rast(nrows=25, ncols=30, xmin=1, xmax=11, ymin=-1, ymax=11) x <- resample(r, s, method="bilinear") opar <- par(no.readonly =TRUE) par(mfrow=c(1,2)) plot(r) plot(x) par(opar) } \keyword{spatial} terra/man/sharedPaths.Rd0000644000175000017500000000124714201035750015032 0ustar nileshnilesh\name{sharedPaths} \docType{methods} \alias{sharedPaths} \alias{sharedPaths,SpatVector-method} \title{ Shared paths } \description{ Get shared paths of line or polygon geometries } \usage{ \S4method{sharedPaths}{SpatVector}(x) } \arguments{ \item{x}{SpatVector of lines or polygons} } \value{ SpatVector } \seealso{ \code{\link{gaps}}, \code{\link{topology}} } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) plot(v, col="light gray") text(v, halo=TRUE) x <- sharedPaths(v) lines(x, col="red", lwd=2) text(x, col="blue", halo=TRUE, cex=0.8) head(x) } \keyword{methods} \keyword{spatial} terra/man/sources.Rd0000644000175000017500000000264114201035750014246 0ustar nileshnilesh\name{sources} \docType{methods} \alias{sources} \alias{sources,SpatRaster-method} \alias{hasValues} \alias{hasValues,SpatRaster-method} \alias{inMemory} \alias{inMemory,SpatRaster-method} \title{Data sources of a SpatRaster} \description{ Get the data sources of a SpatRaster and the number of layers by source. Sources are either files (or similar resources) or "", meaning that they are in memory. You can use \code{hasValues} to check if in-memory layers actually have cell values. } \usage{ \S4method{sources}{SpatRaster}(x, nlyr=FALSE, bands=FALSE) \S4method{hasValues}{SpatRaster}(x) \S4method{inMemory}{SpatRaster}(x, bylayer=FALSE) } \arguments{ \item{x}{SpatRaster} \item{nlyr}{logical. If \code{TRUE} for each source, the number of layers is returned} \item{bands}{logical. If \code{TRUE} for each source, the "bands" used, that is, the layer number in the source file, are returned} \item{bylayer}{logical. If \code{TRUE} a value is retured for each layer instead of for each source} } \value{ A vector of filenames, or \code{""} when there is no filename, if \code{nlyr} and \code{bands} are both \code{FALSE}. Otherwise a \code{data.frame} } \examples{ f <- system.file("ex/elev.tif", package="terra") r <- rast(f) s <- rast(r) values(s) <- 1:ncell(s) rs <- c(r,r,s,r) sources(rs) hasValues(r) x <- rast() hasValues(x) } \keyword{methods} \keyword{spatial} terra/man/is.bool.Rd0000644000175000017500000000304214201035750014124 0ustar nileshnilesh\name{is.bool} \docType{methods} \alias{is.bool} \alias{is.bool,SpatRaster-method} \alias{as.bool} \alias{as.bool,SpatRaster-method} \alias{isTRUE,SpatRaster-method} \alias{isFALSE,SpatRaster-method} \alias{as.logical,SpatRaster-method} \alias{is.int} \alias{is.int,SpatRaster-method} \alias{as.int} \alias{as.int,SpatRaster-method} \alias{as.integer,SpatRaster-method} \title{Raster value types} \description{ The values in a SpatRaster layer are by default numeric, but they can also be logical (Boolean), integer, or categorical Note that \code{as.bool} and \code{as.int} return a new \code{SpatRaster}, whereas \code{is.bool} and \code{is.int} return a \code{logical} value for each layer. For a \code{SpatRaster}, \code{isTRUE} is equivalent to \code{as.bool}, \code{isFALSE} is equivalent to \code{!as.bool}, \code{as.integer} is the same as \code{as.int} and \code{as.logical} is the same as \code{as.bool} } \usage{ \S4method{is.bool}{SpatRaster}(x) \S4method{as.bool}{SpatRaster}(x, filename, ...) \S4method{is.int}{SpatRaster}(x) \S4method{as.int}{SpatRaster}(x, filename, ...) } \arguments{ \item{x}{SpatRaster} \item{filename}{character. Output filename} \item{...}{list with named options for writing files as in \code{\link{writeRaster}}} } \value{ logical or SpatRaster } \examples{ r <- rast(nrows=10, ncols=10, vals=1:100) is.bool(r) z <- as.bool(r) is.bool(z) x <- r > 25 is.bool(x) rr <- r/2 is.int(rr) is.int(round(rr)) } \keyword{methods} \keyword{spatial} terra/man/distance.Rd0000644000175000017500000001210514201035750014351 0ustar nileshnilesh\name{distance} \alias{distance} \alias{distance,SpatRaster,missing-method} \alias{distance,SpatRaster,SpatVector-method} \alias{distance,SpatVector,ANY-method} \alias{distance,SpatVector,SpatVector-method} \alias{distance,matrix,matrix-method} \alias{distance,matrix,missing-method} \title{Geographic distance} \description{ \bold{If \code{x} is a SpatRaster:} If \code{y} is \code{missing} this method computes the distance, for all cells that are \code{NA} in SpatRaster \code{x} to the nearest cell that is not \code{NA}. If argument \code{grid=TRUE}, the distance is computed using a path that goes through the centers of the 8 neighboring cells. If \code{y} is a SpatVector, the distance to that SpatVector is computed for all cells. For lines and polygons this is done after rasterization; and only the overlapping areas of the vector and raster are considered (for now). The distance is always expressed in meter if the coordinate reference system is longitude/latitude, and in map units otherwise. Map units are typically meter, but inspect \code{crs(x)} if in doubt. Results are more precise, sometimes much more precise, when using longitude/latitude rather than a planar coordinate reference system, as these distort distance. \bold{If \code{x} is a SpatVector:} If \code{y} is \code{missing}, a distance matrix between all object in \code{x} is computed. An distance matrix object of class "dist" is returned. If \code{y} is a SpatVector the geographic distance between all objects is computed (and a matrix is returned). If both sets have the same number of points, and \code{pairwise=TRUE}, the distance between each pair of objects is computed, and a vector is returned. The distance is always expressed in meter, except when the coordinate reference system is longitude/latitude AND one of the SpatVector(s) consists of lines or polygons. In that case the distance is in degrees, and thus not very useful (this will be fixed soon). Otherwise, results are more precise, sometimes much more precise, when using longitude/latitude rather than a planar coordinate reference system, as these distort distance. } \usage{ \S4method{distance}{SpatRaster,missing}(x, y, grid=FALSE, filename="", ...) \S4method{distance}{SpatRaster,SpatVector}(x, y, filename="", ...) \S4method{distance}{SpatVector,ANY}(x, y, sequential=FALSE, pairs=FALSE, symmetrical=TRUE) \S4method{distance}{SpatVector,SpatVector}(x, y, pairwise=FALSE) \S4method{distance}{matrix,matrix}(x, y, lonlat, pairwise=FALSE) \S4method{distance}{matrix,missing}(x, y, lonlat, sequential=FALSE) } \arguments{ \item{x}{SpatRaster, SpatVector, or two-column matrix with coordinates (x,y) or (lon,lat)} \item{y}{missing or SpatVector, or two-column matrix} \item{grid}{logical. If \code{TRUE}, distance is computed using a path that goes through the centers of the 8 neighboring cells} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} \item{sequential}{logical. If \code{TRUE}, the distance between sequential geometries is returned} \item{pairwise}{logical. If \code{TRUE} and if x and y have the same size (number of rows), the pairwise distances are returned instead of the distances between all elements} \item{lonlat}{logical. If \code{TRUE} the coordinates are interpreted as angular (longitude/latitude). If \code{FALSE} they are interpreted as planar} \item{pairs}{logical. If \code{TRUE} a "from", "to", "distance" matrix is returned} \item{symmetrical}{logical. If \code{TRUE} and \code{pairs=TRUE}, the distance between a pair is only included once. The distance between geometry 1 and 3 is included, but the (same) distance between 3 and 1 is not} } \value{ SpatRaster or numeric or matrix or distance matrix (object of class "dist") } \note{ The distance unit is in meters. A distance matrix can be coerced into a matrix with \code{as.matrix} } \examples{ #lonlat r <- rast(ncols=36, nrows=18, crs="+proj=longlat +datum=WGS84") r[500] <- 1 d <- distance(r) plot(d / 100000) #planar r <- rast(ncols=36, nrows=18, crs="+proj=utm +zone=1 +datum=WGS84") r[500] <- 1 d <- distance(r) p1 <- vect(rbind(c(0,0), c(90,30), c(-90,-30)), crs="+proj=longlat +datum=WGS84") dp <- distance(r, p1) d <- distance(p1) d as.matrix(d) p2 <- vect(rbind(c(30,-30), c(25,40), c(-9,-3)), crs="+proj=longlat +datum=WGS84") dd <- distance(p1, p2) dd pd <- distance(p1, p2, pairwise=TRUE) pd pd == diag(dd) # polygons, lines crs <- "+proj=utm +zone=1" p1 <- vect("POLYGON ((0 0, 8 0, 8 9, 0 9, 0 0))", crs=crs) p2 <- vect("POLYGON ((5 6, 15 6, 15 15, 5 15, 5 6))", crs=crs) p3 <- vect("POLYGON ((2 12, 3 12, 3 13, 2 13, 2 12))", crs=crs) p <- rbind(p1, p2, p3) L1 <- vect("LINESTRING(1 11, 4 6, 10 6)", crs=crs) L2 <- vect("LINESTRING(8 14, 12 10)", crs=crs) L3 <- vect("LINESTRING(1 8, 12 14)", crs=crs) lns <- rbind(L1, L2, L3) pts <- vect(cbind(c(7,10,10), c(3,5,6)), crs=crs) distance(p1,p3) distance(p) distance(p,pts) distance(p,lns) distance(pts,lns) } \keyword{spatial} terra/man/isvalid.Rd0000644000175000017500000000157014201035750014216 0ustar nileshnilesh\name{valid} \alias{is.valid} \alias{is.valid,SpatVector-method} \alias{makeValid} \alias{makeValid,SpatVector-method} \title{Check or fix polygon validity} \description{ Check the validity of polygons or attempt to fix it } \usage{ \S4method{is.valid}{SpatVector}(x, messages=FALSE, as.points=FALSE) \S4method{makeValid}{SpatVector}(x) } \arguments{ \item{x}{SpatVector} \item{messages}{logical. If \code{TRUE} the error messages are returned} \item{as.points}{logical. If \code{TRUE}, it is attempted to return locations where polygons are invalid as a SpatVector or points} } \value{ logical } \examples{ w <- vect("POLYGON ((0 -5, 10 0, 10 -10, 0 -5))") is.valid(w) w <- vect("POLYGON ((0 -5, 10 0, 10 -10, 4 -2, 0 -5))") is.valid(w) is.valid(w, TRUE) plot(w) points(cbind(4.54, -2.72), cex=2, col="red") } \keyword{spatial} terra/man/rectify.Rd0000644000175000017500000000173214201035750014230 0ustar nileshnilesh\name{rectify} \alias{rectify} \alias{rectify,SpatRaster-method} \title{rectify a SpatRaster} \description{ Rectify a rotated SpatRaster into a non-rotated object } \usage{ \S4method{rectify}{SpatRaster}(x, method="bilinear", aoi=NULL, snap=TRUE, filename="", ...) } \arguments{ \item{x}{SpatRaster to be rectified} \item{method}{character. Method used to for resampling. See \code{\link{resample}}} \item{aoi}{SpatExtent or SpatRaster to crop \code{x} to a smaller area of interest; Using a SpatRaster allowing to set the exact output extent and output resolution} \item{snap}{logical. If \code{TRUE}, the origin and resolution of the output are the same as would the case when \code{aoi = NULL}. Only relevant if \code{aoi} is a \code{SpatExtent}} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \keyword{spatial} terra/man/subset.Rd0000644000175000017500000000302314201035750014063 0ustar nileshnilesh\name{subset} \alias{subset} \alias{subset,SpatRaster-method} \alias{[[,SpatRaster,numeric,missing-method} \alias{[[,SpatRaster,logical,missing-method} \alias{[[,SpatRaster,character,missing-method} \alias{[,SpatRaster,character,missing-method} \alias{[,SpatRasterDataset,numeric,missing-method} \alias{[,SpatRasterDataset,numeric,numeric-method} \alias{[,SpatRasterDataset,logical,missing-method} \alias{[,SpatRasterDataset,character,missing-method} \alias{[[,SpatRasterDataset,ANY,ANY-method} \alias{[,SpatRasterCollection,numeric,missing-method} \alias{$,SpatRaster-method} \alias{$,SpatRasterDataset-method} \title{Subset of a SpatRaster} \description{ Select a subset of layers from a SpatRaster. } \usage{ \S4method{subset}{SpatRaster}(x, subset, filename="", overwrite=FALSE, ...) } \arguments{ \item{x}{SpatRaster} \item{subset}{integer or character. Should indicate the layers (represented as integer or by their names)} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \examples{ s <- rast(system.file("ex/logo.tif", package="terra")) subset(s, 2:3) subset(s, c(3,2,3,1)) #equivalent to s[[ c(3,2,3,1) ]] s[[c("red", "green")]] s$red # expresion based (partial) matching of names with single brackets s["re"] s["^re"] # not with double brackets # s[["re"]] } \keyword{ spatial } terra/man/makeVRT.Rd0000644000175000017500000000451014201035750014071 0ustar nileshnilesh\name{makeVRT} \alias{makeVRT} \title{Make a VRT header file} \description{ Create a VRT header file for a "flat binary" raster file that needs a header file to be able to read it, but does not have it. } \usage{ makeVRT(filename, nrow, ncol, nlyr=1, extent, xmin, ymin, xres, yres=xres, xycenter=TRUE, crs="+proj=longlat", lyrnms="", datatype, NAflag=NA, bandorder="BIL", byteorder="LSB", toptobottom=TRUE, offset=0, scale=1) } \arguments{ \item{filename}{character. raster filename (without ".vrt" exension)} \item{nrow}{positive integer, the number of rows} \item{ncol}{positive integer, the number of columns} \item{nlyr}{positive integer, the number of layers} \item{extent}{SpatExtent or missing} \item{xmin}{numeric. minimum x coordinate (only used if \code{extent} is missing)} \item{ymin}{numeric. minimum y coordinate (only used if \code{extent} is missing)} \item{xres}{postive number. x resolution} \item{yres}{postive number. y resolution)} \item{xycenter}{logical. If \code{TRUE}, \code{xmin} and \code{xmax} represent the coordinates of the center of the ext reme cell, in stead of the coordinates of the outside corner. Only used of \code{extent} is missing} \item{crs}{character. Coordinate reference system description} \item{lyrnms}{character. Layer names} \item{datatype}{character. One of "INT2S", "INT4S", "INT1U", "INT2U", "INT4U", "FLT4S", "FLT8S". If missing, this is guessed from the file size (INT1U for 1 byte per value, INT2S for 2 bytes and FLT4S for 4 bytes per value). This may be wrong because, for example, 2 bytes per value may in fact be INT2U (with the U for unsigned) values} \item{NAflag}{numeric. The value used as the "NA flag"} \item{bandorder}{character. One of "BIL", "BIP", or "BSQ". That is Band Interleaved by Line, or by Pixel, or Band SeQuential} \item{byteorder}{character. One of "LSB", "MSB". "MSB" is common for files generated on Linux systems, whereas "LSB" is common for files generated on windows} \item{toptobottom}{logical. If \code{FALSE}, the values are read bottom to top} \item{offset}{numeric. offset to be applied} \item{scale}{numeric. scale to be applied} } \value{ character (.VRT filename) } \seealso{\code{\link{vrt}} to create a vrt for a collection of raster tiles} \keyword{methods} \keyword{spatial} terra/man/inplace.Rd0000644000175000017500000000473214201035750014201 0ustar nileshnilesh\name{inplace} \alias{set.ext} \alias{set.ext,SpatRaster-method} \alias{set.ext,SpatVector-method} \alias{set.values} \alias{set.values,SpatRaster-method} \alias{set.cats} \alias{set.cats,SpatRaster-method} \alias{set.names} \alias{set.names,SpatRaster-method} \alias{set.names,SpatRasterDataset-method} \alias{set.names,SpatVector-method} \alias{set.names,SpatVectorCollection-method} \alias{set.crs} \alias{set.crs,SpatRaster-method} \alias{set.crs,SpatVector-method} \title{Change values in-place} \description{ These "in-place" replacement methods assign new value to an object without making a copy. That is efficient, but if there is a copy of the object that you made by standard assignment (e.g. with \code{y <- x}), that copy is also changed. \code{set.names} is the in-place replacement version of \code{\link{names<-}}. \code{set.ext} is the in-place replacement version of \code{\link{ext<-}} \code{set.values} is the in-place replacement version of \code{\link{[<-}} \code{set.cats} is the in-place replacement version of \code{\link{categories}} \code{set.crs} is the in-place replacement version of \code{\link{crs<-}} } \usage{ \S4method{set.names}{SpatRaster}(x, value, index=1:nlyr(x), validate=FALSE) \S4method{set.names}{SpatRasterDataset}(x, value, index=1:length(x), validate=FALSE) \S4method{set.names}{SpatVector}(x, value, index=1:ncol(x), validate=FALSE) \S4method{set.ext}{SpatRaster}(x, value) \S4method{set.ext}{SpatVector}(x, value) \S4method{set.crs}{SpatRaster}(x, value) \S4method{set.crs}{SpatVector}(x, value) \S4method{set.values}{SpatRaster}(x, cells, values) \S4method{set.cats}{SpatRaster}(x, layer=1, value, index) } \arguments{ \item{x}{SpatRaster} \item{value}{character (\code{set.names}). For \code{set.cats}: a data.frame with columns (value, category) or vector with category names} \item{index}{positive integer indicating layer(s) to assign a name to, or the index to select the active category} \item{validate}{logical. Make names valid and/or unique?} \item{cells}{cell numbers} \item{values}{replacement values} \item{layer}{positive integer indicating to which layer to you want to assign these categories} } \examples{ s <- rast(ncols=5, nrows=5, nlyrs=3) x <- s names(s) names(s) <- c("a", "b", "c") names(s) names(x) x <- s set.names(s, c("e", "f", "g")) names(s) names(x) set.ext(x, c(0,180,0,90)) set.values(x, 1:10, 5) } \keyword{spatial} terra/man/depth.Rd0000644000175000017500000000112414201035750013662 0ustar nileshnilesh\name{depth} \alias{depth} \alias{depth<-} \alias{depth,SpatRaster-method} \alias{depth<-,SpatRaster-method} \title{depth of SpatRaster layers} \description{ Get or set the depth of the layers of a SpatRaster. Experimental. } \usage{ \S4method{depth}{SpatRaster}(x) \S4method{depth}{SpatRaster}(x)<-value } \arguments{ \item{x}{SpatRaster} \item{value}{numeric vector} } \value{ numeric } \seealso{\code{\link{time}}} \examples{ s <- rast(system.file("ex/logo.tif", package="terra")) depth(s) <- 1:3 depth(s) } \keyword{spatial} terra/man/relate.Rd0000644000175000017500000001011014201035750014025 0ustar nileshnilesh\name{relate} \docType{methods} \alias{relate} \alias{is.related} \alias{relate,SpatVector,SpatVector-method} \alias{relate,SpatVector,missing-method} \alias{relate,SpatVector,SpatExtent-method} \alias{relate,SpatExtent,SpatVector-method} \alias{relate,SpatExtent,SpatExtent-method} \alias{is.related,SpatVector,SpatVector-method} \alias{is.related,SpatVector,SpatExtent-method} \alias{is.related,SpatExtent,SpatVector-method} \title{ relate } \description{ Get a matrix indicating the presence or absence of spatial relationships between geometries. } \usage{ \S4method{relate}{SpatVector,SpatVector}(x, y, relation) \S4method{is.related}{SpatVector,SpatVector}(x, y, relation) \S4method{relate}{SpatVector,missing}(x, y, relation, pairs=FALSE, symmetrical=FALSE) } \arguments{ \item{x}{SpatVector or SpatExtent} \item{y}{missing or as for \code{x}} \item{relation}{character. One of "intersects", "touches", "crosses", "overlaps", "within", "contains", "covers", "coveredby", "disjoint". Or a "DE-9IM" string such as "FF*FF****". See \href{https://en.wikipedia.org/wiki/DE-9IM}{wikipedia} or \href{https://docs.geotools.org/stable/userguide/library/jts/dim9.html}{geotools doc}} \item{pairs}{logical. If \code{TRUE} a "from", "to" matrix is returned for the cases where the requested relation is \code{TRUE}} \item{symmetrical}{logical. If \code{TRUE} and \code{pairs=TRUE}, the relation between a pair is only included once. For example, the relation between geometry 1 and 3 is included, but the relation between 3 and 1 is not. Note that whole some relationships are symmetrical (e.g. "touches"), but that others are not (e.g. "within")} } \value{ matrix (relate) or vector (is.related) } \seealso{ \code{\link{adjacent}}, \code{\link{nearby}}, \code{\link{intersect}}, \code{\link{crop}} } \examples{ # polygons p1 <- vect("POLYGON ((0 0, 8 0, 8 9, 0 9, 0 0))") p2 <- vect("POLYGON ((5 6, 15 6, 15 15, 5 15, 5 6))") p3 <- vect("POLYGON ((8 2, 9 2, 9 3, 8 3, 8 2))") p4 <- vect("POLYGON ((2 6, 3 6, 3 8, 2 8, 2 6))") p5 <- vect("POLYGON ((2 12, 3 12, 3 13, 2 13, 2 12))") p6 <- vect("POLYGON ((10 4, 12 4, 12 7, 11 7, 11 6, 10 6, 10 4))") p <- rbind(p1, p2, p3, p4, p5, p6) plot(p, col=rainbow(6, alpha=.5)) lines(p, lwd=2) text(p) ## relate SpatVectors relate(p1, p2, "intersects") relate(p1, p3, "touches") relate(p1, p5, "disjoint") relate(rbind(p1, p2), p4, "disjoint") ## relate geometries within SpatVectors # which are completely separated? relate(p, relation="disjoint") # which touch (not overlap or within)? relate(p, relation="touches") # which overlap (not merely touch, and not within)? relate(p, relation="overlaps") # which are within (not merely overlap)? relate(p, relation="within") # do they touch or overlap or are within? relate(p, relation="intersects") all(relate(p, relation="intersects") == (relate(p, relation="overlaps") | relate(p, relation="touches") | relate(p, relation="within"))) #for polygons, "coveredby" is "within" relate(p, relation="coveredby") # polygons, lines, and points pp <- rbind(p1, p2) L1 <- vect("LINESTRING(1 11, 4 6, 10 6)") L2 <- vect("LINESTRING(8 14, 12 10)") L3 <- vect("LINESTRING(1 8, 12 14)") lns <- rbind(L1, L2, L3) pts <- vect(cbind(c(7,10,10), c(3,5,6))) plot(pp, col=rainbow(2, alpha=.5)) text(pp, paste0("POL", 1:2), halo=TRUE) lines(pp, lwd=2) lines(lns, col=rainbow(3), lwd=4) text(lns, paste0("L", 1:3), halo=TRUE) points(pts, cex=1.5) text(pts, paste0("PT", 1:3), halo=TRUE, pos=4) relate(lns, relation="crosses") relate(lns, pp, relation="crosses") relate(lns, pp, relation="touches") relate(lns, pp, relation="intersects") relate(lns, pp, relation="within") # polygons can contain lines or points, not the other way around relate(lns, pp, relation="contains") relate(pp, lns, relation="contains") # points and lines can be covered by polygons relate(lns, pp, relation="coveredby") relate(pts, pp, "within") relate(pts, pp, "touches") relate(pts, lns, "touches") } \keyword{methods} \keyword{spatial} terra/man/diff.Rd0000644000175000017500000000120614201035750013467 0ustar nileshnilesh\name{diff} \alias{diff} \alias{diff,SpatRaster-method} \title{Lagged differences} \description{ Compute the difference between consecutive layers in a SpatRaster. } \usage{ \S4method{diff}{SpatRaster}(x, lag=1, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{lag}{postive integer indicating which lag to use} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \examples{ s <- rast(system.file("ex/logo.tif", package="terra")) d <- diff(s) } \keyword{methods} \keyword{spatial} terra/man/makeTiles.Rd0000644000175000017500000000237614201035750014506 0ustar nileshnilesh\name{makeTiles} \docType{methods} \alias{tiles} \alias{tiles,SpatRaster-method} \alias{makeTiles} \alias{makeTiles,SpatRaster-method} \title{Make tiles} \description{ Divide a SpatRaster into "tiles". The cell of another SpatRaster (normally with a much lower resolution) are used to define the tiles. } \usage{ \S4method{makeTiles}{SpatRaster}(x, y, filename="tile_.tif", extend=FALSE, na.rm=FALSE, ...) } \arguments{ \item{x}{SpatRaster} \item{y}{SpatRaster or SpatVector} \item{filename}{character. Output filename template. Filenames will be altered by adding the tile number for each tile} \item{extend}{logical. If \code{TRUE}, the extent of \code{y} is expanded to assure that it covers all of \code{x}} \item{na.rm}{logical. If \code{TRUE}, tiles with only missing values are ignored} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ character (filenames) } \seealso{ \code{\link{vrt}} to create a virtual raster from tiles } \examples{ r <- rast(ncols=100, nrows=100) values(r) <- 1:ncell(r) x <- rast(ncols=2, nrows=2) filename <- paste0(tempfile(), "_.tif") ff <- makeTiles(r, x, filename) ff vrt(ff) } \keyword{methods} \keyword{spatial} terra/man/width.Rd0000644000175000017500000000311714201035750013701 0ustar nileshnilesh\name{width} \docType{methods} \alias{width} \alias{clearance} \alias{width,SpatVector-method} \alias{clearance,SpatVector-method} \title{ SpatVector geometric properties } \description{ \code{width} returns the minimum diameter of the geometry, defined as the smallest band that contains the geometry, where a band is a strip of the plane defined by two parallel lines. This can be thought of as the smallest hole that the geometry can be moved through, with a single rotation. \code{clearance} returns the minimum clearance of a geometry. The minimum clearance is the smallest amount by which a vertex could be moved to produce an invalid polygon, a non-simple linestring, or a multipoint with repeated points. If a geometry has a minimum clearance of 'mc', it can be said that: No two distinct vertices in the geometry are separated by less than 'mc' No vertex is closer than 'mc' to a line segment of which it is not an endpoint. If the minimum clearance cannot be defined for a geometry (such as with a single point, or a multipoint whose points are identical, NA is returned. } \usage{ \S4method{width}{SpatVector}(x, as.lines=FALSE) \S4method{clearance}{SpatVector}(x, as.lines=FALSE) } \arguments{ \item{x}{SpatVector of lines or polygons} \item{as.lines}{logical. If \code{TRUE} lines are returned that define the width or clearance} } \value{ numeric or SpatVector } \seealso{ \code{\link{minRect}} } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) width(v) clearance(v) } \keyword{methods} \keyword{spatial} terra/man/flip.Rd0000644000175000017500000000230214201035750013507 0ustar nileshnilesh\name{flip} \docType{methods} \alias{flip} \alias{flip,SpatRaster-method} \alias{flip,SpatVector-method} \alias{rev} \alias{rev,SpatRaster-method} \title{Flip or reverse a raster} \description{ Flip the values of a SpatRaster by inverting the order of the rows (\code{vertical=TRUE}) or the columns (\code{vertical=FALSE}). \code{rev} is the same as a horizontal *and* a vertical flip. } \usage{ \S4method{flip}{SpatRaster}(x, direction="vertical", filename="", ...) \S4method{flip}{SpatVector}(x, direction="vertical") \S4method{rev}{SpatRaster}(x) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{direction}{character. Should (partially) match "vertical" to flip by rows, or "horizontal" to flip by columns} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{ \code{\link{trans}}, \code{\link{rotate}} } \examples{ r <- rast(nrow=18, ncol=36) m <- matrix(1:ncell(r), nrow=18) values(r) <- as.vector(t(m)) rx <- flip(r, direction="h") values(r) <- as.vector(m) ry <- flip(r, direction="v") v <- rev(r) } \keyword{spatial} terra/man/NAflag.Rd0000644000175000017500000000213614201035747013720 0ustar nileshnilesh\name{NAflag} \alias{NAflag<-} \alias{NAflag} \alias{NAflag,SpatRaster-method} \alias{NAflag<-,SpatRaster-method} \title{Set the NA flag} \description{ The main purpose of this method is to allow correct reading of a SpatRaster that is based on a file that has an incorrect NA flag. The file is not changed, but flagged value is set to NA when values are read from the file ("lazy evaluation"). In contrast, if the values are in memory the change is made immediately. To change values, it is generally better to use \code{\link{classify}} } \usage{ \S4method{NAflag}{SpatRaster}(x) \S4method{NAflag}{SpatRaster}(x)<-value } \arguments{ \item{x}{SpatRaster} \item{value}{numeric. The value to be interpreted as NA; set this before reading the values from the file. This can be a single value, or multiple values, one for each data source (file / subdataset)} } \value{ none or numeric } \seealso{ \code{\link{classify}} } \examples{ s <- rast(system.file("ex/logo.tif", package="terra"))[[1]] NAflag(s) <- 255 plot(s) NAflag(s) } \keyword{ spatial } terra/man/disaggregate.Rd0000644000175000017500000000257214201035750015214 0ustar nileshnilesh\name{disagg} \docType{methods} \alias{disagg} \alias{disagg,SpatRaster-method} \alias{disagg,SpatVector-method} \title{Disaggregate raster cells or vector geometries} \description{ \code{SpatRaster}: Create a SpatRaster with a higher resolution (smaller cells). The values in the new SpatRaster are the same as in the larger original cells. \code{SpatVector}: Separate multi-objects (points, lines, polygons) into single objects. } \usage{ \S4method{disagg}{SpatRaster}(x, fact, method="near", filename="", ...) \S4method{disagg}{SpatVector}(x) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{fact}{positive integer. Aggregation factor expressed as number of cells in each direction (horizontally and vertically). Or two integers (horizontal and vertical aggregation factor) or three integers (when also aggregating over layers)} \item{method}{character. Either "near" for nearest or "bilinear" for bilinear interpolation} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \seealso{\code{\link{aggregate}}, \code{\link{resample}}} \value{ SpatRaster } \examples{ r <- rast(ncols=10, nrows=10) rd <- disagg(r, fact=c(10, 2)) ncol(rd) nrow(rd) values(r) <- 1:ncell(r) rd <- disagg(r, fact=c(4, 2)) } \keyword{methods} \keyword{spatial} terra/man/mask.Rd0000644000175000017500000000407314201035750013517 0ustar nileshnilesh\name{mask} \docType{methods} \alias{mask} \alias{mask,SpatRaster,SpatRaster-method} \alias{mask,SpatRaster,SpatVector-method} \alias{mask,SpatVector,SpatVector-method} \title{Mask values in a SpatRaster or SpatVector} \description{ If \code{x} is a \code{SpatRaster}: Create a new SpatRaster that has the same values as SpatRaster \code{x}, except for the cells that are \code{NA} (or another \code{maskvalue}) in another SpatRaster (the 'mask'), or not covered by a SpatVector. These cells become \code{NA} (or another \code{updatevalue}). If \code{x} is a \code{SpatVector}: Select geometries of \code{x} that intersect, or not intersect, with the geometries of \code{y}. } \usage{ \S4method{mask}{SpatRaster,SpatRaster}(x, mask, inverse=FALSE, maskvalues=NA, updatevalue=NA, filename="", ...) \S4method{mask}{SpatRaster,SpatVector}(x, mask, inverse=FALSE, updatevalue=NA, touches=TRUE, filename="", ...) \S4method{mask}{SpatVector,SpatVector}(x, mask, inverse=FALSE) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{mask}{SpatRaster or SpatVector} \item{inverse}{logical. If \code{TRUE}, areas on mask that are _not_ the \code{maskvalue} are masked} \item{maskvalues}{numeric. The value(s) in \code{mask} that indicates the cells of \code{x} that should become \code{updatevalue} (default = \code{NA})} \item{updatevalue}{numeric. The value that cells of \code{x} should become if they are not covered by \code{mask} (and not \code{NA})} \item{touches}{logical. If \code{TRUE}, all cells touched by lines or polygons will be masked, not just those on the line render path, or whose center point is within the polygon} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{SpatRaster} \seealso{\link{crop}} \examples{ r <- rast(ncols=10, nrows=10) m <- rast(ncols=10, nrows=10) values(r) <- 1:100 set.seed(1965) x <- round(3 * runif(ncell(r))) x[x==0] <- NA values(m) <- x mr <- mask(r, m) } \keyword{methods} \keyword{spatial} terra/man/stretch.Rd0000644000175000017500000000367314201035750014245 0ustar nileshnilesh\name{stretch} \alias{stretch} \alias{stretch,SpatRaster-method} \title{Stretch} \description{ Linear or histogram equalization stretch of values in a SpatRaster. For linear stretch, provide the desired output range (\code{minv} and \code{maxv}) and the lower and upper bounds in the original data, either as quantiles (\code{minq} and \code{maxq}, or as cell values (\code{smin} and \code{smax}). If \code{smin} and \code{smax} are both not \code{NA}, \code{minq} and \code{maxq} are ignored. For histogram equalization, these arguments are ignored, but you can provide the desired scale of the output. } \usage{ \S4method{stretch}{SpatRaster}(x, minv=0, maxv=255, minq=0, maxq=1, smin=NA, smax=NA, histeq=FALSE, scale=1, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{minv}{numeric >= 0 and smaller than maxv. lower bound of stretched value} \item{maxv}{numeric <= 255 and larger than maxv. upper bound of stretched value} \item{minq}{numeric >= 0 and smaller than maxq. lower quantile bound of original value. Ignored if smin is supplied} \item{maxq}{numeric <= 1 and larger than minq. upper quantile bound of original value. Ignored if smax is supplied} \item{smin}{numeric < smax. user supplied lower value for the layers, to be used instead of a quantile computed by the function itself} \item{smax}{numeric > smin. user supplied upper value for the layers, to be used instead of a quantile computed by the function itself} \item{histeq}{logical. If \code{TRUE} histogram equalization is used instead of linear stretch} \item{scale}{numeric. The scale (maximum value) of the output if \code{histeq=TRUE}} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \examples{ r <- rast(nc=10, nr=10) values(r) <- rep(1:25, 4) rs <- stretch(r) s <- c(r, r*2) sr <- stretch(s) } \keyword{spatial} terra/man/subset-vector.Rd0000644000175000017500000000230514201035750015365 0ustar nileshnilesh\name{subset-vector} \alias{subset,SpatVector-method} \alias{[,SpatVector,missing,missing-method} \alias{[,SpatVector,missing,numeric-method} \alias{[,SpatVector,missing,character-method} \alias{[,SpatVector,numeric,missing-method} \alias{[,SpatVector,numeric,numeric-method} \alias{[,SpatVector,numeric,character-method} \alias{[,SpatVector,logical,missing-method} \alias{[,SpatVector,logical,character-method} \alias{[,SpatVector,logical,numeric-method} \alias{[,SpatVector,data.frame,missing-method} \alias{[,SpatVector,matrix,missing-method} \title{Subset of a SpatVector} \description{ Select a subset of variables or records from a SpatVector. } \usage{ \S4method{subset}{SpatVector}(x, subset, drop=FALSE) } \arguments{ \item{x}{SpatVector} \item{subset}{logical expression indicating elements or rows to keep: missing values are taken as false} \item{drop}{logical. If \code{TRUE}, the geometries will be dropped, and a data.frame is returned} } \value{ SpatVector or, if \code{drop=TRUE}, a data.frame. } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) v[2:3,] v[,2:3] subset(v, v$NAME_1 == "Diekirch") } \keyword{ spatial } terra/man/quantile.Rd0000644000175000017500000000257414201035750014412 0ustar nileshnilesh\name{quantile} \docType{methods} \alias{quantile} \alias{quantile,SpatRaster-method} \alias{quantile,SpatVector-method} \title{Quantiles of spatial data} \description{ Compute quantiles for each cell across the layers of a SpatRaster. You can use use \code{\link{global}(x, fun=quantile)} to instead compute quantiles across cells for each layer. You can also use this method to compute quantiles of the numeric variables of a SpatVector. } \usage{ \S4method{quantile}{SpatRaster}(x, probs=seq(0, 1, 0.25), na.rm=FALSE, filename="", ...) \S4method{quantile}{SpatVector}(x, probs=seq(0, 1, 0.25), ...) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{probs}{numeric vector of probabilities with values in [0,1]} \item{na.rm}{logical. If \code{TRUE}, \code{NA}'s are removed from \code{x} before the quantiles are computed} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster with layers representing quantiles } \seealso{ \code{\link{app}} } \examples{ r <- rast(system.file("ex/logo.tif", package="terra")) rr <- c(r/2, r, r*2) qr <- quantile(rr) qr \dontrun{ # same but slower qa <- app(rr, quantile) } #quantile by layer instead of by cell qg <- global(r, quantile) } \keyword{methods} \keyword{spatial} terra/man/compareGeom.Rd0000644000175000017500000000255214201035750015022 0ustar nileshnilesh\name{compareGeom} \alias{compareGeom} \alias{compareGeom,SpatRaster,SpatRaster-method} \title{Compare geometries of SpatRasters} \description{ Evaluate whether two SpatRaster objects have the same extent, number of rows and columns, projection, resolution, and origin (or a subset of these comparisons). } \usage{ \S4method{compareGeom}{SpatRaster,SpatRaster}(x, y, ..., lyrs=FALSE, crs=TRUE, warncrs=FALSE, ext=TRUE, rowcol=TRUE, res=FALSE, stopOnError=TRUE) } \arguments{ \item{x}{SpatRaster} \item{y}{SpatRaster} \item{...}{Additional SpatRasters} \item{lyrs}{logical. If \code{TRUE}, the number of layers is compared} \item{crs}{logical. If \code{TRUE}, coordinate reference systems are compared} \item{warncrs}{logical. If \code{TRUE}, a warning is given if the crs is different (instead of an error)} \item{ext}{logical. If \code{TRUE}, bounding boxes are compared} \item{rowcol}{logical. If \code{TRUE}, number of rows and columns of the objects are compared} \item{res}{logical. If \code{TRUE}, resolutions are compared (redundant when checking extent and rowcol)} \item{stopOnError}{logical. If \code{TRUE}, code execution stops if raster do not match} } \examples{ r1 <- rast() r2 <- rast() r3 <- rast() compareGeom(r1, r2, r3) nrow(r3) <- 10 \dontrun{ compareGeom(r1, r3) } } \keyword{spatial} terra/man/units.Rd0000644000175000017500000000154414201035750013726 0ustar nileshnilesh\name{units} \alias{units} \alias{units<-} \alias{units,SpatRaster-method} \alias{units<-,SpatRaster-method} \alias{units,SpatRasterDataset-method} \alias{units<-,SpatRasterDataset-method} \title{units of SpatRaster or SpatRasterDataSet} \description{ Get or set the units of the layers of a SpatRaster or the datasets in a SpatRasterDataSet. } \usage{ \S4method{units}{SpatRaster}(x) \S4method{units}{SpatRaster}(x)<-value \S4method{units}{SpatRasterDataset}(x) \S4method{units}{SpatRasterDataset}(x)<-value } \arguments{ \item{x}{SpatRaster} \item{value}{character} } \value{ character } \seealso{\code{\link{time}, \link{names}}} \examples{ s <- rast(system.file("ex/logo.tif", package="terra")) units(s) <- c("m/s", "kg", "ha") units(s) s units(s) <- "kg" units(s) } \keyword{spatial} terra/man/unique.Rd0000644000175000017500000000256114201035750014072 0ustar nileshnilesh\name{unique} \docType{methods} \alias{unique} \alias{unique,SpatRaster-method} \alias{unique,SpatRaster,ANY-method} \alias{unique,SpatVector-method} \alias{unique,SpatVector,ANY-method} \title{Unique values} \description{ This function returns the unique values in a SpatRaster or removes duplicates in a SpatVector. } \usage{ \S4method{unique}{SpatRaster}(x, incomparables=FALSE) \S4method{unique}{SpatVector}(x, incomparables=FALSE, ...) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{incomparables}{logical. If \code{FALSE} and \code{x} is a SpatRaster: the unique values are determined for all layers together, and the result is a matrix. If \code{TRUE}, each layer is evaluated separately, and a list is returned. If \code{x} is a SpatVector this argument is as for a \code{data.frame}.} \item{...}{additional arguments passed on to \code{\link[base]{unique}}} } \value{ If \code{x} is a SpatRaster: data.frame or list (if \code{incomparables=FALSE}) If \code{x} is a SpatVector: SpatVector } \examples{ r <- rast(ncols=5, nrows=5) values(r) <- rep(1:5, each=5) unique(r) s <- c(r, round(r/3)) unique(s) unique(s,TRUE) v <- vect(cbind(x=c(1:5,1:5), y=c(5:1,5:1)), crs="+proj=utm +zone=1 +datum=WGS84") nrow(v) u <- unique(v) nrow(u) values(v) <- c(1:5, 1:3, 5:4) unique(v) } \keyword{spatial} terra/man/which.Rd0000644000175000017500000000127314201035750013665 0ustar nileshnilesh\name{which.lyr} \docType{methods} \alias{which.lyr} \alias{which.lyr,SpatRaster-method} \title{Which cells are TRUE?} \description{ This method returns a single layer SpatRaster with cell values that are the first layer in the input that has the value is not zero (FALSE), and, hence, is \code{TRUE}. } \usage{ \S4method{which.lyr}{SpatRaster}(x) } \arguments{ \item{x}{SpatRaster} } \value{ SpatRaster } \seealso{\code{\link{isTRUE}}, \code{\link{which}}, See \code{\link{Summary-methods}} for \code{which.min} and \code{which.max}} \examples{ s <- rast(system.file("ex/logo.tif", package="terra")) x <- which.lyr(s > 100) } \keyword{spatial} terra/man/dots.Rd0000644000175000017500000000231414201035750013531 0ustar nileshnilesh\name{dots} \docType{methods} \alias{dots} \alias{dots,SpatVector-method} \title{Make a dot-density map} \description{ Create the dots for a dot-density map and add these to the current map. Dot-density maps are made to display count data. For example of population counts, where each dot represents n persons. The dots are returned as a \code{SpatVector}. It there is an active graphics device, the dots are added to it with \code{\link{points}}. } \usage{ \S4method{dots}{SpatVector}(x, field, size, ...) } \arguments{ \item{x}{SpatVector} \item{field}{character of numeric indicating field name. Or numeric vector of the same length as \code{x}} \item{size}{positive number indicating the number of cases associated with each dot} \item{...}{graphical arguments passed to \code{points}} } \value{ SpatVector (invisibly) } \seealso{ \code{\link{plot}}, \code{\link{cartogram}}, \code{\link{points}} } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) v$population <- 1000*(1:12)^2 plot(v, lwd=3, col="light gray", border="white") d <- dots(v, "population", 1000, col="red", cex=.75) lines(v) d } \keyword{methods} \keyword{spatial} terra/man/click.Rd0000644000175000017500000000425514201035750013653 0ustar nileshnilesh\name{click} \alias{click} \alias{click,SpatRaster-method} \alias{click,SpatVector-method} \alias{click,missing-method} \title{Query by clicking on a map} \description{ Click on a map (plot) to get the coordinates or the values of a SpatRaster or SpatVector at that location. For a SpatRaster you can also get the coordinates and cell number of the location. } \usage{ \S4method{click}{SpatRaster}(x, n=10, id=FALSE, xy=FALSE, cell=FALSE, type="p", show=TRUE, ...) \S4method{click}{SpatVector}(x, n=10, id=FALSE, xy=FALSE, type="p", show=TRUE, ...) \S4method{click}{missing}(x, n=10, id=FALSE, type="p", show=TRUE, ...) } \arguments{ \item{x}{SpatRaster or SpatVector, or missing} \item{n}{number of clicks on the plot (map)} \item{id}{logical. If \code{TRUE}, a numeric ID is shown on the map that corresponds to the row number of the output} \item{xy}{logical. If \code{TRUE}, xy coordinates are included in the output} \item{cell}{logical. If \code{TRUE}, cell numbers are included in the output} \item{type}{one of "n", "p", "l" or "o". If "p" or "o" the points are plotted; if "l" or "o" they are joined by lines. See ?locator} \item{show}{logical. Print the values after each click?} \item{...}{additional graphics parameters used if type != "n" for plotting the locations. See ?locator} } \value{ The value(s) of \code{x} at the point(s) clicked on (or touched by the box drawn). } \note{ The plot only provides the coordinates for a spatial query, the values are read from the SpatRaster that is passed as an argument. Thus you can extract values from an object that has not been plotted, as long as it spatially overlaps with with the extent of the plot. Unless the process is terminated prematurely values at at most \code{n} positions are determined. The identification process can be terminated by hitting Esc, or by clicking the right mouse button and selecting "Stop" from the menu, or from the "Stop" menu on the graphics window. } \seealso{\link{draw}} \examples{ \dontrun{ r <-rast(system.file("ex/elev.tif", package="terra")) plot(r) click(r, n=1) ## now click on the plot (map) }} \keyword{ spatial } terra/man/gaps.Rd0000644000175000017500000000120414201035750013507 0ustar nileshnilesh\name{gaps} \docType{methods} \alias{gaps} \alias{gaps,SpatVector-method} \alias{gaps,SpatVector,SpatExtent-method} \title{Find gaps between polygons} \description{ Get the gaps between polygons of a SpatVector } \usage{ \S4method{gaps}{SpatVector}(x) } \arguments{ \item{x}{SpatVector} } \value{ SpatVector } \seealso{ \code{\link{sharedPaths}}, \code{\link{topology}}, and \code{\link{fillHoles}} to get or remove polygon holes } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) h <- convHull(v[-12], "NAME_1") g <- gaps(h) } \keyword{methods} \keyword{spatial} terra/man/persp.Rd0000644000175000017500000000153514201035750013715 0ustar nileshnilesh\name{persp} \docType{methods} \alias{persp} \alias{persp,SpatRaster-method} \title{Perspective plot} \description{ Perspective plot of a SpatRaster. This is an implementation of a generic function in the graphics package. } \usage{ \S4method{persp}{SpatRaster}(x, maxcells=100000, ...) } \arguments{ \item{x}{SpatRaster. Only the first layer is used} \item{maxcells}{integer > 0. Maximum number of cells to use for the plot. If \code{maxpixels < ncell(x)}, \code{spatSample(method="regular")} is used before plotting} \item{...}{Any argument that can be passed to \code{\link[graphics]{persp}} (graphics package)} } \seealso{ \code{\link[graphics]{persp}}, \code{contour}, \code{plot} } \examples{ r <- rast(system.file("ex/elev.tif", package="terra")) persp(r) } \keyword{methods} \keyword{spatial} terra/man/time.Rd0000644000175000017500000000135414201035750013521 0ustar nileshnilesh\name{time} \alias{time} \alias{time<-} \alias{time,SpatRaster-method} \alias{time<-,SpatRaster-method} \title{time of SpatRaster layers} \description{ Get or set the time of the layers of a SpatRaster. } \usage{ \S4method{time}{SpatRaster}(x) \S4method{time}{SpatRaster}(x)<-value } \seealso{\code{\link{depth}}} \arguments{ \item{x}{SpatRaster} \item{value}{"Date", "POSIXt", or numeric} } \value{ Date } \examples{ s <- rast(system.file("ex/logo.tif", package="terra")) # Date" d <- as.Date("2001-05-04") + 0:2 time(s) <- d time(s) # POSIX (time stored as seconds) time(s) <- as.POSIXlt(d) time(s) # "raw" time time(s) <- as.numeric(d) time(s) } \keyword{spatial} terra/man/draw.Rd0000644000175000017500000000201414201035750013512 0ustar nileshnilesh\name{draw} \alias{draw} \alias{draw,character-method} \alias{draw,missing-method} \title{ Draw a polygon, line, extent, or points } \description{ Draw on a plot (map) to get a SpatVector or SpatExtent object for later use. After calling the function, start clicking on the map. When you are done, press \code{ESC}. You can also preset the maximum number of clicks. } \usage{ \S4method{draw}{character}(x="extent", col="red", lwd=2, id=FALSE, n=1000, ...) } \arguments{ \item{x}{character. The type of object to draw. One of "extent", "polygon", "line", or "points"} \item{col}{the color to be used} \item{lwd}{the width of the lines to be drawn} \item{id}{logical. If \code{TRUE}, a numeric ID is shown on the map} \item{n}{the maximum number of clicks (does not apply when \code{x=="extent"} in which case \code{n} is always 2} \item{...}{additional graphics arguments for drawing} } \value{ SpatVector or SpatExtent } \seealso{ \code{\link{click}} } \keyword{ spatial } terra/man/crosstab.Rd0000644000175000017500000000203114201035750014374 0ustar nileshnilesh\name{crosstab} \docType{methods} \alias{crosstab} \alias{crosstab,SpatRaster,missing-method} \title{Cross-tabulate} \description{ Cross-tabulate the layers of a SpatRaster to create a contingency table. } \usage{ \S4method{crosstab}{SpatRaster,missing}(x, digits=0, long=FALSE, useNA=FALSE) } \arguments{ \item{x}{SpatRaster} \item{digits}{integer. The number of digits for rounding the values before cross-tabulation} \item{long}{logical. If \code{TRUE} the results are returned in 'long' format data.frame instead of a table} \item{useNA}{logical, indicting if the table should includes counts of \code{NA} values} } \value{ A table or data.frame } \seealso{ \code{\link{freq}}, \code{\link{zonal}} } \examples{ r <- s <- rast(nc=5, nr=5) set.seed(1) values(r) <- runif(ncell(r)) * 2 values(s) <- runif(ncell(r)) * 3 x <- c(r, s) crosstab(x) rs <- r/s r[1:5] <- NA s[20:25] <- NA x <- c(r, s, rs) crosstab(x, useNA=TRUE, long=TRUE) } \keyword{methods} \keyword{spatial} terra/man/barplot.Rd0000644000175000017500000000276714201035747014245 0ustar nileshnilesh\name{barplot} \docType{methods} \alias{barplot} \alias{barplot,SpatRaster-method} \title{Bar plot of a SpatRaster} \description{Create a barplot of the values of a the first layer of a SpatRaster. For large datasets a regular sample with a size of approximately \code{maxcells} is used.} \usage{ \S4method{barplot}{SpatRaster}(height, maxcell=1000000, digits=0, breaks=NULL, col, ...) } \arguments{ \item{height}{SpatRaster} \item{maxcell}{integer. To regularly subsample very large datasets} \item{digits}{integer used to determine how to \code{\link{round}} the values before tabulating. Set to \code{NULL} or to a large number if you do not want any rounding } \item{breaks}{breaks used to group the data as in \code{\link[base]{cut}}} \item{col}{a color generating function such as \code{\link{rainbow}} (the default), or a vector of colors} \item{...}{additional arguments for plotting as in \code{\link[graphics]{barplot}}} } \seealso{ \code{\link{hist}, \link{boxplot}} } \value{ A numeric vector (or matrix, when \code{beside = TRUE}) of the coordinates of the bar midpoints, useful for adding to the graph. See \code{\link[graphics]{barplot}} } \examples{ f <- system.file("ex/elev.tif", package="terra") r <- rast(f) barplot(r, digits=-1, las=2, ylab="Frequency") op <- par(no.readonly = TRUE) par(mai = c(1, 2, .5, .5)) barplot(r, breaks=10, col=c("red", "blue"), horiz=TRUE, digits=NULL, las=1) par(op) } \keyword{methods} \keyword{spatial} terra/man/dimensions.Rd0000644000175000017500000000607514201035750014740 0ustar nileshnilesh\name{dimensions} \docType{methods} \alias{size} \alias{length} \alias{ncol} \alias{nrow} \alias{ncell} \alias{nlyr} \alias{nsrc} \alias{dim} \alias{res} \alias{xres} \alias{yres} \alias{ncol<-} \alias{nrow<-} \alias{nlyr<-} \alias{res<-} \alias{size,SpatRaster-method} \alias{ncell,ANY-method} \alias{nrow,SpatRaster-method} \alias{ncol,SpatRaster-method} \alias{nrow,SpatRasterDataset-method} \alias{ncol,SpatRasterDataset-method} \alias{nrow<-,SpatRaster,numeric-method} \alias{ncol<-,SpatRaster,numeric-method} \alias{nlyr,SpatRasterDataset-method} \alias{res<-,SpatRaster,numeric-method} \alias{nlyr,SpatRaster-method} \alias{nlyr<-,SpatRaster,numeric-method} \alias{nsrc,SpatRaster-method} \alias{ncell,SpatRaster-method} \alias{ncell,SpatRasterDataset-method} \alias{length,SpatRasterDataset-method} \alias{length,SpatRasterCollection-method} \alias{dim,SpatRaster-method} \alias{dim,SpatRasterDataset-method} \alias{dim<-,SpatRaster-method} \alias{dim,SpatVector-method} \alias{dim,SpatVectorProxy-method} \alias{res,SpatRasterDataset-method} \alias{res,SpatRaster-method} \alias{res<-,SpatRaster-method} \alias{xres,SpatRaster-method} \alias{yres,SpatRaster-method} \alias{nrow,SpatVector-method} \alias{ncol,SpatVector-method} \alias{length,SpatVector-method} \alias{length,SpatVectorCollection-method} \title{Dimensions of a SpatRaster or SpatVector and related objects} \description{ Get the number of rows (\code{nrow}), columns (\code{ncol}), cells (\code{ncell}), layers (\code{nlyr}), sources (\code{nsrc}), the size \code{size} (\code{nlyr(x)*ncell(x)}), or spatial resolution of a SpatRaster. \code{length} returns the number of sub-datasets in a SpatRasterDataset or SpatVectorCollection. For a SpatVector \code{length(x)} is the same as \code{nrow(x)}. You can also set the number of rows or columns or layers. When setting dimensions, all cell values are dropped. } \usage{ \S4method{ncol}{SpatRaster}(x) \S4method{nrow}{SpatRaster}(x) \S4method{nlyr}{SpatRaster}(x) \S4method{ncell}{SpatRaster}(x) \S4method{nsrc}{SpatRaster}(x) \S4method{ncol}{SpatRaster,numeric}(x)<-value \S4method{nrow}{SpatRaster,numeric}(x)<-value \S4method{nlyr}{SpatRaster,numeric}(x)<-value \S4method{res}{SpatRaster}(x) \S4method{res}{SpatRaster,numeric}(x)<-value \S4method{xres}{SpatRaster}(x) \S4method{yres}{SpatRaster}(x) \S4method{ncol}{SpatVector}(x) \S4method{nrow}{SpatVector}(x) \S4method{length}{SpatVector}(x) } \arguments{ \item{x}{SpatRaster or SpatVector or related objecs} \item{value}{For ncol and nrow: positive integer. For res: one or two positive numbers } } \value{ integer } \seealso{ \link{ext}} \examples{ r <- rast() ncol(r) nrow(r) nlyr(r) dim(r) nsrc(r) ncell(r) rr <- c(r,r) nlyr(rr) nsrc(rr) ncell(rr) nrow(r) <- 18 ncol(r) <- 36 # equivalent to dim(r) <- c(18, 36) dim(r) dim(r) <- c(10, 10, 5) dim(r) xres(r) yres(r) res(r) res(r) <- 1/120 # different xres and yres res(r) <- c(1/120, 1/60) } \keyword{spatial} terra/man/buffer.Rd0000644000175000017500000000262314201035750014034 0ustar nileshnilesh\name{buffer} \alias{buffer} \alias{buffer,SpatRaster-method} \alias{buffer,SpatVector-method} \title{Create a buffer around vector geometries or raster patches} \description{ Calculate a buffer around all cells that are not \code{NA} in a SpatRaster, or around the geometries of a SpatVector) Note that the distance unit of the buffer \code{width} parameter is meters if the CRS is (\code{+proj=longlat}), and in map units (typically also meters) if not. } \usage{ \S4method{buffer}{SpatRaster}(x, width, filename="", ...) \S4method{buffer}{SpatVector}(x, width, quadsegs=10) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{width}{numeric. Unit is meter if \code{x} has a longitude/latitude CRS, or mapunits in other cases. Should be > 0 for SpatRaster} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} \item{quadsegs}{positive integer. Number of line segments to use to draw a quart circle} } \value{SpatRaster} \seealso{ \code{\link{distance}} } \examples{ r <- rast(ncols=36, nrows=18) v <- rep(NA, ncell(r)) v[500] <- 1 values(r) <- v b <- buffer(r, width=5000000) plot(b) v <- vect(rbind(c(10,10), c(0,60)), crs="+proj=merc") b <- buffer(v, 20) plot(b) points(v) crs(v) <- "+proj=longlat" b <- buffer(v, 1500000) plot(b) points(v) } \keyword{spatial} terra/man/centroids.Rd0000644000175000017500000000064614201035750014560 0ustar nileshnilesh\name{centroids} \alias{centroids} \alias{centroids,SpatVector-method} \title{Get centroids} \description{ Get the centroids for the polygons of a SpatVector } \usage{ \S4method{centroids}{SpatVector}(x) } \arguments{ \item{x}{SpatVector} } \value{SpatVector of points} \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) x <- centroids(v) } \keyword{spatial} terra/man/values.Rd0000644000175000017500000000466114201035750014066 0ustar nileshnilesh\name{values} \docType{methods} \alias{values} \alias{values,SpatRaster-method} \alias{values,SpatVector-method} \title{Cell values and geometry attributes} \description{ Get the cell values of a SpatRaster or the attributes of a SpatVector. By default all values returned are numeric. This is because a vector or matrix can only store one data type, and a SpatRaster may consist of multiple data types. However, with \code{values(x, dataframe=TRUE)} and \code{\link[terra]{as.data.frame}(x)} the values returned match the type of each layer, and can be numeric, logical, integer, or factor. } \usage{ \S4method{values}{SpatRaster}(x, mat=TRUE, dataframe=FALSE, row=1, nrows=nrow(x), col=1, ncols=ncol(x), na.rm=FALSE, ...) \S4method{values}{SpatVector}(x, ...) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{mat}{logical. If \code{TRUE}, values are returned as a matrix instead of as a vector, except when dataframe is \code{TRUE}} \item{dataframe}{logical. If \code{TRUE}, values are returned as a \code{data.frame} instead of as a vector (also if matrix is \code{TRUE})} \item{row}{positive integer. Row number to start from, should be between 1 and nrow(x)} \item{nrows}{positive integer. How many rows?} \item{col}{positive integer. Column number to start from, should be between 1 and ncol(x)} \item{ncols}{positive integer. How many columns? Default is the number of columns left after the start column} \item{na.rm}{logical. Remove \code{NA}s?} \item{...}{additional arguments passed to \code{\link{data.frame}}} } \details{ If \code{x} is a \code{SpatRaster}, and \code{mat=FALSE}, the values are returned as a vector. In cell-order by layer. If \code{mat=TRUE}, a matrix is returned in which the values of each layer are represented by a column (with \code{ncell(x)} rows). The values per layer are in cell-order, that is, from top-left, to top-right and then down by row. Use \code{\link{as.matrix}(x, wide=TRUE)} for an alternative matrix representation where the number of rows and columns matches that of \code{x}. } \value{ matrix or data.frame } \seealso{\code{\link{values<-}}, \code{\link{focalValues}}} \examples{ f <- system.file("ex/elev.tif", package="terra") r <- rast(f) r x <- values(r) x[3650:3655, ] r[3650:3655] ff <- system.file("ex/lux.shp", package="terra") v <- vect(ff) y <- values(v) head(y) } \keyword{spatial} \keyword{methods} terra/man/terrain.Rd0000644000175000017500000001014314201035750014223 0ustar nileshnilesh\name{terrain} \alias{terrain} \alias{terrain,SpatRaster-method} \title{terrain characteristic} \description{ Compute terrain characteristic from elevation data. The elevation values should be in the same units as the map units (typically meter) for projected (planar) raster data. They should be in meter when the coordinate reference system is longitude/latitude. } \usage{ \S4method{terrain}{SpatRaster}(x, v="slope", neighbors=8, unit="degrees", filename="", ...) } \arguments{ \item{x}{SpatRaster, single layer with elevation values. Values should have the same unit as the map units, or in meters when the crs is longitude/latitude} \item{v}{character. One or more of these options: slope, aspect, TPI, TRI, roughness, flowdir (see Details)} \item{unit}{character. "degrees" or "radians" for the output of "slope" and "aspect"} \item{neighbors}{integer. Indicating how many neighboring cells to use to compute slope or aspect with. Either 8 (queen case) or 4 (rook case)} \item{filename}{character. Output filename} \item{...}{list. Options for writing files as in \code{\link{writeRaster}}} } \details{ When \code{neighbors=4}, slope and aspect are computed according to Fleming and Hoffer (1979) and Ritter (1987). When \code{neigbors=8}, slope and aspect are computed according to Horn (1981). The Horn algorithm may be best for rough surfaces, and the Fleming and Hoffer algorithm may be better for smoother surfaces (Jones, 1997; Burrough and McDonnell, 1998). If slope = 0, aspect is set to 0.5*pi radians (or 90 degrees if unit="degrees"). When computing slope or aspect, the coordinate reference system of \code{x} must be known for the algorithm to differentiate between planar and longitude/latitude data. \code{terrain} is not vectorized over "neighbors" or "unit" -- only the first value is used. flowdir returns the "flow direction" (of water), that is the direction of the greatest drop in elevation (or the smallest rise if all neighbors are higher). They are encoded as powers of 2 (0 to 7). The cell to the right of the focal cell is 1, the one below that is 2, and so on: \tabular{rrr}{ 32 \tab64 \tab 128\cr 16 \tab x \tab 1 \cr 8 \tab 4 \tab 2 \cr } If two cells have the same drop in elevation, a random cell is picked. That is not ideal as it may prevent the creation of connected flow networks. ArcGIS implements the approach of Greenlee (1987) and I might adopt that in the future. The terrain indices are according to Wilson et al. (2007), as in \href{https://gdal.org/programs/gdaldem.html}{gdaldem}. TRI (Terrain Ruggedness Index) is the mean of the absolute differences between the value of a cell and the value of its 8 surrounding cells. TPI (Topographic Position Index) is the difference between the value of a cell and the mean value of its 8 surrounding cells. Roughness is the difference between the maximum and the minimum value of a cell and its 8 surrounding cells. Such measures can also be computed with the \code{\link{focal}} function: f <- matrix(1, nrow=3, ncol=3) TRI <- focal(x, w=f, fun=function(x, ...) sum(abs(x[-5]-x[5]))/8) TPI <- focal(x, w=f, fun=function(x, ...) x[5] - mean(x[-5])) rough <- focal(x, w=f, fun=function(x, ...) {max(x) - min(x)}, na.rm=TRUE) } \references{ Burrough, P., and R.A. McDonnell, 1998. Principles of Geographical Information Systems. Oxford University Press. Fleming, M.D. and Hoffer, R.M., 1979. Machine processing of Landsat MSS data and DMA topographic data for forest cover type mapping. LARS Technical Report 062879. Laboratory for Applications of Remote Sensing, Purdue University, West Lafayette, Indiana. Horn, B.K.P., 1981. Hill shading and the reflectance map. Proceedings of the IEEE 69:14-47 Jones, K.H., 1998. A comparison of algorithms used to compute hill terrain as a property of the DEM. Computers & Geosciences 24: 315-323 Ritter, P., 1987. A vector-based terrain and aspect generation algorithm. Photogrammetric Engineering and Remote Sensing 53: 1109-1111 } \examples{ f <- system.file("ex/elev.tif", package="terra") r <- rast(f) x <- terrain(r, "slope") } \keyword{spatial} terra/man/writeRaster.Rd0000644000175000017500000001025614201035750015077 0ustar nileshnilesh\name{writeRaster} \alias{writeRaster,SpatRaster,character-method} \alias{writeRaster} \title{Write raster data to a file} \description{ Write a SpatRaster object to a file. } \usage{ \S4method{writeRaster}{SpatRaster,character}(x, filename, overwrite=FALSE, ...) } \arguments{ \item{x}{SpatRaster} \item{filename}{character. Output filename. Can be a single filename, or as many filenames as \code{nlyr(x)} to write a file for each layer} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{...}{additional arguments for for writing files. See Details } } \value{ SpatRaster. This function is used for the side-effect of writing values to a file. } \seealso{ see \code{\link{writeCDF}} for writing NetCDF files. } \details{ In writeRaster, and in other methods that generate SpatRaster objects, options for writing raster files to disk can be provided as additional arguments or, in a few cases, as the \code{wopt} argument (a named list) if the additional arguments are already used for a different purpose. The following options are available: \tabular{ll}{ \bold{name} \tab \bold{description}\cr \code{datatype}\tab values for \code{datatype} are "INT1U", "INT2U", "INT2S", "INT4U", "INT4S", "FLT4S", "FLT8S". The first three letters indicate whether the datatype is integer (whole numbers) of a real number (decimal numbers), the fourth character indicates the number of bytes used (allowing for large numbers and/or more precision), and the "S" or "U" indicate whether the values are signed (both negative and positive) or unsigned (positive values only).\cr \code{filetype}\tab file format expresses as \href{https://gdal.org/drivers/raster/index.html}{GDAL driver names}. If this argument is not supplied, the driver is derived from the filename.\cr \code{gdal}\tab GDAL driver specific datasource creation options. See the GDAL documentation. For example, with the \href{https://gdal.org/drivers/raster/gtiff.html}{GeoTiff file format} you can use \code{gdal=c("COMPRESS=DEFLATE", "TFW=YES")}.\cr \code{tempdir}\tab the path where temporary files are to be written to.\cr \code{progress}\tab positive integer. If the number of chunks is larger, a progress bar is shown.\cr \code{memfrac}\tab numeric between 0 and 0.9 (higher values give a warning). The fraction of available RAM that terra is allowed to use.\cr \code{memmax}\tab memmax - the maximum amount of RAM (in GB) that terra can use when processing a raster dataset. Should be less than what is detected (see \code{link{mem_info}}, and higher values are ignored. Set it to a negative number or NA to ignore this value). \cr \code{names}\tab output layer names.\cr \code{NAflag}\tab numeric. value to represent missing (\code{NA} or \code{NaN}) values. See note\cr \code{verbose}\tab logical. If \code{TRUE} debugging information is printed.\cr \code{steps}\tab postive integers. In how many steps (chunks) do you want to process the data (for debugging)\cr \code{todisk}\tab logical. If \code{TRUE} processing operates as if the dataset is very large and needs to be written to a temporary file (for debugging).\cr } } \note{ GeoTiff files are, by default, written with LZW compression. If you do not want compression, use \code{gdal="COMPRESS=NONE"}. When writing integer values the lowest available value (given the datatype) is used to represent \code{NA} for signed types, and the highest value is used for unsigned values. This can be a problem with byte data (between 0 and 255) as the value 255 is reserved for \code{NA}. To keep the value 255, you need to set another value as \code{NAflag}, or do not set a \code{NAflag} (with \code{NAflag=NA}) } \examples{ library(terra) r <- rast(nrows=5, ncols=5, vals=1:25) # create a temporary filename for the example f <- file.path(tempdir(), "test.tif") writeRaster(r, f, overwrite=TRUE) writeRaster(r, f, overwrite=TRUE, gdal=c("COMPRESS=NONE", "TFW=YES","of=COG"), datatype='INT1U') ## Or with a wopt argument: writeRaster(r, f, overwrite=TRUE, wopt= list(gdal=c("COMPRESS=NONE", "of=COG"), datatype='INT1U')) ## remove the file unlink(f) } \keyword{ spatial } \keyword{ methods } terra/man/transpose.Rd0000644000175000017500000000135414201035750014601 0ustar nileshnilesh\name{transpose} \docType{methods} \alias{t} \alias{t,SpatRaster-method} \alias{t,SpatVector-method} \alias{trans} \alias{trans,SpatRaster-method} \title{Transpose} \description{ Transpose a SpatRaster } \usage{ \S4method{t}{SpatRaster}(x) \S4method{t}{SpatVector}(x) \S4method{trans}{SpatRaster}(x, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{ \code{\link{flip}, \link{rotate}} } \examples{ r <- rast(nrows=18, ncols=36) values(r) <- 1:ncell(r) tr1 <- t(r) tr2 <- trans(r) ttr <- trans(tr2) } \keyword{spatial} terra/man/erase.Rd0000644000175000017500000000225614201035750013664 0ustar nileshnilesh\name{erase} \docType{methods} \alias{erase} \alias{erase,SpatVector,SpatVector-method} \alias{erase,SpatVector,missing-method} \alias{erase,SpatVector,SpatExtent-method} \title{ Erase parts of a SpatVector object} \description{ Erase parts of a SpatVector with another SpatVector or with a SpatExtent. You can also erase (parts of) polygons with the other polygons of the same SpatVector. } \usage{ \S4method{erase}{SpatVector,SpatVector}(x, y) \S4method{erase}{SpatVector,missing}(x) \S4method{erase}{SpatVector,SpatExtent}(x, y) } \arguments{ \item{x}{SpatVector} \item{y}{SpatVector or SpatExtent} } \value{ SpatVector or SpatExtent } \seealso{ \code{\link{intersect}}, \code{\link{crop}}. The equivalent for SpatRaster is \code{\link{mask}} } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) e <- ext(5.6, 6, 49.55, 49.7) x <- erase(v, e) p <- vect("POLYGON ((5.8 49.8, 6 49.9, 6.15 49.8, 6 49.6, 5.8 49.8))") y <- erase(v, p) # self-erase h <- convHull(v[-12], "NAME_1") he <- erase(h) plot(h, lwd=2, border="red", lty=2) lines(he, col="gray", lwd=3) } \keyword{methods} \keyword{spatial} terra/man/select.Rd0000644000175000017500000000244014201035750014037 0ustar nileshnilesh\name{sel} \docType{methods} \alias{sel} \alias{sel,SpatRaster-method} \alias{sel,SpatVector-method} \title{ Spatial selection } \description{ Geometrically subset SpatRaster or SpatVector (to be done) by drawing on a plot (map). } \usage{ \S4method{sel}{SpatRaster}(x, ...) \S4method{sel}{SpatVector}(x, use="rec", draw=TRUE, col="cyan", ...) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{use}{character indicating what to draw. One of "rec" (rectangle) or "pol" (polygon)} \item{draw}{logial. If \code{TRUE} the selection is drawn on the map} \item{col}{color to be used for drawing if \code{draw=TRUE}} \item{...}{additional graphics arguments for drawing} } \seealso{ \code{\link{crop}} and \code{\link{intersect}} to make an intersection and \code{\link{click}} and \code{\link{text}} to see cell values or geometry attributes } \value{ SpatRaster or SpatVector } \examples{ \dontrun{ # select a subset of a SpatRaster r <- rast(nrows=10, ncols=10) values(r) <- 1:ncell(r) plot(r) s <- sel(r) # now click on the map twice # plot the selection on a new canvas: x11() plot(s) # vector f <- system.file("ex/lux.shp", package="terra") v <- vect(f) plot(v) x <- sel(v) # now click on the map twice x } } \keyword{spatial} terra/man/freq.Rd0000644000175000017500000000263614201035750013524 0ustar nileshnilesh\name{freq} \docType{methods} \alias{freq} \alias{freq,SpatRaster-method} \title{Frequency table} \description{ Frequency table of the values of a SpatRaster. \code{NA}s are not counted unless \code{value=NA}. } \usage{ \S4method{freq}{SpatRaster}(x, digits=0, value=NULL, bylayer=TRUE, usenames=FALSE) } \arguments{ \item{x}{SpatRaster} \item{digits}{integer. Used for rounding the values before tabulation. Ignored if \code{NA}} \item{value}{numeric. An optional single value to only count the number of cells with that value. This value can be \code{NA}} \item{bylayer}{logical. If \code{TRUE} tabulation is done by layer} \item{usenames}{logical. If \code{TRUE} layers are identified by their names instead of their numbers. Only relevant if \code{bylayer} is \code{TRUE}} } \value{ \code{matrix} or \code{data.frame} with 3 columns (layer, value, count) or, if \code{bylayer=FALSE} two columns (value, count). If any of the layers of \code{x} is categorical, there is an additional column (label). A \code{data.frame} is returned if \code{usenames=TRUE} or if any of the layers of \code{x} is categorical. } \examples{ r <- rast(nrows=10, ncols=10) set.seed(2) values(r) <- sample(5, ncell(r), replace=TRUE) freq(r) x <- c(r, r/3) freq(x, bylayer=FALSE) freq(x) freq(x, digits=1) freq(x, digits=-1) freq(x, value=5) } \keyword{spatial} \keyword{univar} terra/man/geomtype.Rd0000644000175000017500000000205514201035750014413 0ustar nileshnilesh\name{geomtype} \docType{methods} \alias{geomtype} \alias{geomtype,SpatVector-method} \alias{geomtype,SpatVectorProxy-method} \alias{geomtype,Spatial-method} \alias{datatype} \alias{datatype,SpatVector-method} \alias{is.points} \alias{is.lines} \alias{is.polygons} \alias{is.points,SpatVector-method} \alias{is.lines,SpatVector-method} \alias{is.polygons,SpatVector-method} \title{Geometry type of a SpatVector} \description{ Get the geometry type (points, lines, or polygons) of a SpatVector or the data types of the fields (attributes, variables) of a SpatVector. } \usage{ \S4method{geomtype}{SpatVector}(x) \S4method{datatype}{SpatVector}(x) \S4method{is.points}{SpatVector}(x) \S4method{is.lines}{SpatVector}(x) \S4method{is.polygons}{SpatVector}(x) } \arguments{ \item{x}{SpatVector} } \value{character} \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) geomtype(v) is.polygons(v) is.lines(v) is.points(v) names(v) datatype(v) } \keyword{methods} \keyword{spatial} terra/man/focal3D.Rd0000644000175000017500000000536514201035750014044 0ustar nileshnilesh\name{focal3D} \alias{focal3D} \alias{focal3D,SpatRaster-method} \title{Three-dimensional focal values} \description{ Calculate focal ("moving window") values for the three-dimensional neighborhood (window) of focal cells. See \code{\link{focal}} for two-dimensional focal computation. } \usage{ \S4method{focal3D}{SpatRaster}(x, w=3, fun=mean, ..., na.policy="all", fillvalue=NA, pad=FALSE, padvalue=fillvalue, expand=FALSE, silent=TRUE, filename="", overwrite=FALSE, wopt=list()) } \arguments{ \item{x}{SpatRaster} \item{w}{window. A rectangular prism (cuboid) defined by three numbers or by a three-dimensional array. The values are used as weights, and are usually zero, one, NA, or fractions. The window used must have odd dimensions. If you desire to use even sides, you can use an array, and pad the values with rows and/or columns that contain only \code{NA}s. } \item{fun}{function that takes multiple numbers, and returns one or multiple numbers for each focal area. For example mean, modal, min or max} \item{...}{additional arguments passed to \code{fun} such as \code{na.rm}} \item{na.policy}{character. Can be used to determine the cells of \code{x} for which focal values should be computed. Must be one of "all" (compute for all cells), "only" (only for cells that are \code{NA}) or "omit" (skip cells that are \code{NA}). Note that the value of this argument does not affect which cells around each focal cell are included in the computations (use \code{na.rm=TRUE} to ignore cells that are \code{} for that)} \item{fillvalue}{numeric. The value of the cells in the virtual rows and columns outside of the raster} \item{pad}{logical. Add virtual layers before the first and after the last layer} \item{padvalue}{numeric. The value of the cells in the virtual layers} \item{expand}{logical. Add virtual layers before the first or after the last layer that are the same as the first or last layers. If \code{TRUE}, arguments \code{pad} and \code{padvalue} are ignored} \item{silent}{logical. If \code{TRUE} error messages are printed that may occur when trying \code{fun} to determine the length of the returned value. This can be useful in debugging a function passed to \code{fun} that does not work} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{SpatRaster} \seealso{ \code{\link{focal}}} \examples{ r <- rast(system.file("ex/logo.tif", package="terra")) x <- focal3D(r, c(5,5,3), na.rm=TRUE) a <- array(c(0,1,0,1,1,1,0,1,0, rep(1,9), 0,1,0,1,1,1,0,1,0), c(3,3,3)) a[a==0] <- NA z <- focal3D(r, a, na.rm=TRUE) } \keyword{spatial} terra/man/shift.Rd0000644000175000017500000000171314201035750013677 0ustar nileshnilesh\name{shift} \docType{methods} \alias{shift} \alias{shift,SpatRaster-method} \alias{shift,SpatExtent-method} \alias{shift,SpatVector-method} \title{Shift} \description{ Shift a SpatRaster, SpatVector or SpatExtent to another location. } \usage{ \S4method{shift}{SpatRaster}(x, dx=0, dy=0, filename="", ...) \S4method{shift}{SpatVector}(x, dx=0, dy=0) \S4method{shift}{SpatExtent}(x, dx=0, dy=0) } \arguments{ \item{x}{SpatRaster, SpatVector or SpatExtent} \item{dx}{numeric. The shift in horizontal direction} \item{dy}{numeric. The shift in vertical direction} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ Same as \code{x} } \seealso{ \code{\link{flip}}, \code{\link{rotate}}} \examples{ r <- rast(xmin=0, xmax=1, ymin=0, ymax=1) r <- shift(r, dx=1, dy=-1) e <- ext(r) shift(e, 5, 5) } \keyword{spatial} terra/man/describe.Rd0000644000175000017500000000316714201035750014347 0ustar nileshnilesh\name{describe} \alias{describe} \alias{describe,character-method} \title{describe} \description{ Describe the properties of spatial data in a file as generated with the "GDALinfo" tool. } \usage{ \S4method{describe}{character}(x, sds=FALSE, meta=FALSE, parse=FALSE, options="", print=FALSE, open_opt="") } \arguments{ \item{x}{character. The name of a file with spatial data. Or a fully specified subdataset within a file such as \code{"NETCDF:\"AVHRR.nc\":NDVI"}} \item{sds}{logical. If \code{TRUE} the description or metadata of the subdatasets is returned (if available)} \item{meta}{logical. Get the file level metadata instead} \item{parse}{logical. If \code{TRUE}, metadata for subdatasets is parsed into components (if \code{meta=TRUE})} \item{options}{character. A vector of valid options (if \code{meta=FALSE}) including "json", "mm", "stats", "hist", "nogcp", "nomd", "norat", "noct", "nofl", "checksum", "proj4", "listmdd", "mdd " where specifies a domain or 'all', "wkt_format " where value is one of 'WKT1', 'WKT2', 'WKT2_2015', or 'WKT2_2018', "sd " where is the name or identifier of a sub-dataset. See \url{https://gdal.org/programs/gdalinfo.html}. Ignored if \code{sds=TRUE}} \item{print}{logical. If \code{TRUE}, print the results} \item{open_opt}{character. Driver specific open options} } \value{ character (invisibly, if \code{print=FALSE}) } \examples{ f <- system.file("ex/elev.tif", package="terra") describe(f) describe(f, meta=TRUE) #g <- describe(f, options=c("json", "nomd", "proj4")) #head(g) } \keyword{spatial} terra/man/plotRGB.Rd0000644000175000017500000000744414201035750014102 0ustar nileshnilesh\name{plotRGB} \docType{methods} \alias{plotRGB} \alias{plotRGB,SpatRaster-method} \title{Red-Green-Blue plot of a multi-layered SpatRaster} \description{ Make a Red-Green-Blue plot based on three layers in a SpatRaster. The layers (sometimes referred to as "bands" because they may represent different bandwidths in the electromagnetic spectrum) are combined such that they represent the red, green and blue channel. This function can be used to make "true" (or "false") color images from Landsat and other multi-spectral satellite images. Note that the margins of the plot are set to zero (no axes or titles are visible) but can be set with the \code{mar} argument. An alternative way to plot RGB images is to first use \code{\link{colorize}} to create a single layer SpatRaster with a color-table and then use \code{\link[terra]{plot}}. } \usage{ \S4method{plotRGB}{SpatRaster}(x, r=1, g=2, b=3, a=NULL, scale, maxcell=500000, mar=0, stretch=NULL, ext=NULL, smooth=FALSE, colNA="white", alpha, bgalpha, addfun=NULL, zlim=NULL, zlimcol=NULL, axes=FALSE, xlab="", ylab="", asp=NULL, add=FALSE, interpolate, ...) } \arguments{ \item{x}{SpatRaster} \item{r}{integer. Index of the Red channel, between 1 and nlyr(x)} \item{g}{integer. Index of the Green channel, between 1 and nlyr(x)} \item{b}{integer. Index of the Blue channel, between 1 and nlyr(x)} \item{a}{integer. Index of the alpha (transparancy) channel, between 1 and nlyr(x). If not NULL, argument \code{alpha} is ignored} \item{scale}{integer. Maximum (possible) value in the three channels. Defaults to 255 or to the maximum value of \code{x} if that is known and larger than 255} \item{maxcell}{integer > 0. Maximum number of pixels to use} \item{mar}{numeric vector recycled to length 4 to set the margins of the plot. Use \code{mar=NULL} or \code{mar=NA} to not set the margins} \item{stretch}{character. Option to stretch the values to increase contrast: "lin" (linear) or "hist" (histogram)} \item{ext}{An \code{\link{SpatExtent}} object to zoom in to a region of interest (see \code{\link{draw}})} \item{smooth}{logical. If \code{TRUE}, smooth the image when drawing to get the appearance of a higher spatial resolution} \item{colNA}{color for the background (\code{NA} values)} \item{alpha}{transparency. Integer between 0 (transparent) and 255 (opaque)} \item{bgalpha}{Background transparency. Integer between 0 (transparent) and 255 (opaque)} \item{addfun}{Function to add additional items such as points or polygons to the plot (map). See \code{\link{plot}}} \item{zlim}{numeric vector of length 2. Range of values to plot (optional)} \item{zlimcol}{If \code{NULL} the values outside the range of zlim get the color of the extremes of the range. If zlimcol has any other value, the values outside the zlim range get the color of \code{NA} values (see colNA)} \item{axes}{logical. If \code{TRUE} axes are drawn (and arguments such as \code{main="title"} will be honored)} \item{xlab}{character. Label of x-axis} \item{ylab}{character. Label of y-axis} \item{asp}{numeric. Aspect (ratio of x and y. If NULL, and appropriate value is computed to match data for the longitude/latitude coordinate reference system, and 1 for planar coordinate reference systems} \item{add}{logical. If \code{TRUE} add values to current plot} \item{interpolate}{logical. Do not use, to be removed} \item{...}{graphical parameters as in \code{\link{plot}} or \code{\link{rasterImage}}} } \seealso{ \code{\link{plot}}, \code{\link{colorize}}, \code{\link{RGB}} } \examples{ b <- rast(system.file("ex/logo.tif", package="terra")) plotRGB(b) plotRGB(b, mar=c(2,2,2,2)) plotRGB(b, 3, 2, 1) b[1000:2000] <- NA plotRGB(b, 3, 2, 1, stretch='hist') } \keyword{methods} \keyword{spatial} terra/man/readwrite.Rd0000644000175000017500000000630014201035750014545 0ustar nileshnilesh\name{read and write} \docType{methods} \alias{readStart} \alias{readStop} \alias{readValues} \alias{writeStart} \alias{writeStop} \alias{writeValues} \alias{fileBlocksize} \alias{readStart,SpatRaster-method} \alias{readStop,SpatRaster-method} \alias{readStart,SpatRasterDataset-method} \alias{readStop,SpatRasterDataset-method} \alias{readValues,SpatRaster-method} \alias{writeStart,SpatRaster,character-method} \alias{writeStop,SpatRaster-method} \alias{writeValues,SpatRaster,vector-method} \title{Read from, or write to, file} \description{ Methods to read from or write chunks of values to or from a file. These are low level methods for programmers. Use writeRaster if you want to save an entire SpatRaster to file in one step. It is much easier to use. To write chunks, begin by opening a file with \code{writeStart}, then write values to it in chunks. When writing is done close the file with \code{writeStop}. } \usage{ \S4method{readStart}{SpatRaster}(x) \S4method{readStop}{SpatRaster}(x) \S4method{readValues}{SpatRaster}(x, row=1, nrows=nrow(x), col=1, ncols=ncol(x), mat=FALSE, dataframe=FALSE, ...) \S4method{writeStart}{SpatRaster,character}(x, filename="", overwrite=FALSE, n=4, ...) \S4method{writeStop}{SpatRaster}(x) \S4method{writeValues}{SpatRaster,vector}(x, v, start, nrows) fileBlocksize(x) } \arguments{ \item{x}{SpatRaster} \item{filename}{character. Output filename} \item{v}{vector with cell values to be written} \item{start}{integer. Row number (counting starts at 1) from where to start writing \code{v}} \item{row}{positive integer. Row number to start from, should be between 1 and nrow(x)} \item{nrows}{positive integer. How many rows?} \item{col}{positive integer. Column number to start from, should be between 1 and ncol(x)} \item{ncols}{positive integer. How many columns? Default is the number of columns left after the start column} \item{mat}{logical. If \code{TRUE}, values are returned as a numeric matrix instead of as a vector, except when dataframe is \code{TRUE}. If any of the layers of \code{x} is a factor, the level index is returned, not the label. Use \code{dataframe=TRUE} to get the labels} \item{dataframe}{logical. If \code{TRUE}, values are returned as a \code{data.frame} instead of as a vector (also if matrix is \code{TRUE})} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{n}{poistive integer indicating how many copies the data may be in memory at any point in time. This is used to determine how many blocks (large) datasets need to be read} \item{...}{ For \code{writeStart}: additional arguments for writing files as in \code{\link{writeRaster}} For \code{readValues}: additional arguments for \code{\link{data.frame}} (and thus only relevant when \code{dataframe=TRUE}) } } \value{ \code{readValues} returns a vector, matrix, or data.frame \code{writeStart} returns a list that can be used for processing the file in chunks. The other methods invisibly return a logical value indicating whether they were succesful or not. Their purpose is the side-effect of opening or closing files. } \keyword{ spatial } \keyword{ methods } terra/man/classify.Rd0000644000175000017500000001001014201035750014365 0ustar nileshnilesh\name{classify} \docType{methods} \alias{classify} \alias{classify,SpatRaster-method} \title{Classify (or reclassify) cell values} \description{ Classify values of a SpatRaster. The function (re-)classifies groups of values to other values. The classification is done based on the argument \code{rcl}. You can classify ranges by specifying a three-column matrix "from-to-becomes" or change specific values by using a two-column matrix "is-becomes". You can also supply a vector with "cuts" or the "number of cuts". With "from-to-becomes" or "is-becomes" classification is done in the row order of the matrix. Thus, if there are overlapping ranges or values, the first time a number is within a range determines the reclassification value. With "cuts" the values are sorted, so that the order in which they are provided does not matter. } \usage{ \S4method{classify}{SpatRaster}(x, rcl, include.lowest=FALSE, right=TRUE, othersNA=FALSE, brackets=TRUE, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{rcl}{matrix for classification. This matrix must have 1, 2 or 3 columns. If there are three columns, the first two columns are "from" "to" of the input values, and the third column "becomes" has the new value for that range. The two column matrix ("is", "becomes") can be useful for classifying integer values. In that case, the arguments \code{right} and \code{include.lowest} are ignored. A single column matrix (or a vector) is interpreted as a set of cuts if there is more than one value. In that case the values are classified based on their location in-between the cut-values. If a single number is provided, that is used to make that number of cuts, at equal intervals between the lowest and highest values of the SpatRaster. } \item{include.lowest}{logical, indicating if a value equal to the lowest value in \code{rcl} (or highest value in the second column, for \code{right=FALSE}) should be included.} \item{right}{logical. If \code{TRUE}, the intervals are closed on the right (and open on the left). If \code{FALSE} they are open at the right and closed at the left. "open" means that the extreme value is *not* included in the interval. Thus, right-closed and left open is \code{(0,1] = {x | 0 < x <= 1}}. You can also close both sides with \code{right=NA}, that is only meaningful if you "from-to-becomes" classification with integers. For example to classify 1-5 -> 1, 6-10 -> 2, 11-15 -> 3. That may be easier to read and write than the equivalent 1-5 -> 1, 5-10 -> 2, 10-15 -> 3 with \code{right=TRUE} and \code{include.lowest=TRUE}} \item{othersNA}{logical. If \code{TRUE}, values that are not matched become \code{NA}. If \code{FALSE}, they retain their original value.} \item{brackets}{logical. If \code{TRUE}, intervals are have parenthesis or brackets around them to indicate whether they are open or closed. Only applies if \code{rcl} is a vector (or single column matrix)} \item{filename}{character. Output filename} \item{...}{Additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{\code{\link{subst}} for simpler from-to replacement} \note{ For model-based classification see \code{\link{predict}} } \examples{ r <- rast(ncols=10, nrows=10) values(r) <- (0:99)/99 ## from-to-becomes # classify the values into three groups # all values >= 0 and <= 0.25 become 1, etc. m <- c(0, 0.25, 1, 0.25, 0.5, 2, 0.5, 1, 3) rclmat <- matrix(m, ncol=3, byrow=TRUE) rc1 <- classify(r, rclmat, include.lowest=TRUE) ## cuts # equivalent to the, but now a categorical SpatRaster is returned rc2 <- classify(r, c(0, 0.25, 0.5, 1), include.lowest=TRUE, brackets=TRUE) freq(rc2) ## is-becomes x <- round(r*3) unique(x) # replace 0 with NA y <- classify(x, cbind(0, NA)) unique(y) # multiple replacements m <- rbind(c(2, 200), c(3, 300)) m rcx1 <- classify(x, m) unique(rcx1) rcx2 <- classify(x, m, othersNA=TRUE) unique(rcx2) } \keyword{spatial} terra/man/predict.Rd0000644000175000017500000001370614201035750014221 0ustar nileshnilesh\name{predict} \docType{methods} \alias{predict} \alias{predict,SpatRaster-method} \title{Spatial model predictions} \description{ Make a SpatRaster object with predictions from a fitted model object (for example, obtained with \code{glm} or \code{randomForest}). The first argument is a SpatRaster object with the predictor variables. The \code{\link{names}} in the Raster object should exactly match those expected by the model. Any regression like model for which a predict method has been implemented (or can be implemented) can be used. This approach of using model predictions is commonly used in remote sensing (for the classification of satellite images) and in ecology, for species distribution modeling. } \usage{ \S4method{predict}{SpatRaster}(object, model, fun=predict, ..., factors=NULL, const=NULL, na.rm=FALSE, index=NULL, cores=1, cpkgs=NULL, filename="", overwrite=FALSE, wopt=list()) } \arguments{ \item{object}{SpatRaster} \item{model}{fitted model of any class that has a "predict" method (or for which you can supply a similar method as \code{fun} argument. E.g. glm, gam, or randomForest} \item{fun}{function. The predict function that takes \code{model} as first argument. The default value is \code{predict}, but can be replaced with e.g. predict.se (depending on the type of model), or your own custom function} \item{...}{additional arguments for \code{fun}} \item{const}{data.frame. Can be used to add a constant value as a predictor variable so that you do not need to make a SpatRaster layer for it} \item{factors}{list with levels for factor variables. The list elements should be named with names that correspond to names in \code{object} such that they can be matched. This argument may be omitted for standard models such as "glm" as the predict function will extract the levels from the \code{model} object, but it is necessary in some other cases (e.g. cforest models from the party package)} \item{na.rm}{logical. If \code{TRUE}, cells with \code{NA} values in the predictors are removed from the computation. This option prevents errors with models that cannot handle \code{NA} values. In most other cases this will not affect the output. An exception is when predicting with a model that returns predicted values even if some (or all!) variables are \code{NA} } \item{index}{integer. To select subset of output variables} \item{cores}{positive integer. If \code{cores > 1}, a 'parallel' package cluster with that many cores is created and used} \item{cpkgs}{character. The package(s) that need to be loaded on the nodes to be able to run the model.predict function (see examples)} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{list with named options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \examples{ logo <- rast(system.file("ex/logo.tif", package="terra")) names(logo) <- c("red", "green", "blue") p <- matrix(c(48, 48, 48, 53, 50, 46, 54, 70, 84, 85, 74, 84, 95, 85, 66, 42, 26, 4, 19, 17, 7, 14, 26, 29, 39, 45, 51, 56, 46, 38, 31, 22, 34, 60, 70, 73, 63, 46, 43, 28), ncol=2) a <- matrix(c(22, 33, 64, 85, 92, 94, 59, 27, 30, 64, 60, 33, 31, 9, 99, 67, 15, 5, 4, 30, 8, 37, 42, 27, 19, 69, 60, 73, 3, 5, 21, 37, 52, 70, 74, 9, 13, 4, 17, 47), ncol=2) xy <- rbind(cbind(1, p), cbind(0, a)) # extract predictor values for points e <- extract(logo, xy[,2:3]) # combine with response (excluding the ID column) v <- data.frame(cbind(pa=xy[,1], e)) #build a model, here with glm model <- glm(formula=pa~., data=v) #predict to a raster r1 <- predict(logo, model) plot(r1) points(p, bg='blue', pch=21) points(a, bg='red', pch=21) # logistic regression model <- glm(formula=pa~., data=v, family="binomial") r1log <- predict(logo, model, type="response") # use a modified function to get the probability and standard error # from the glm model. The values returned by "predict" are in a list, # and this list needs to be transformed to a matrix predfun <- function(model, data) { v <- predict(model, data, se.fit=TRUE) cbind(p=as.vector(v$fit), se=as.vector(v$se.fit)) } r2 <- predict(logo, model, fun=predfun) # principal components of a SpatRaster # here using sampling to simulate an object too large # to feed all its values to prcomp sr <- values(spatSample(logo, 100, as.raster=TRUE)) pca <- prcomp(sr) x <- predict(logo, pca) plot(x) ## parallelization \dontrun{ ## simple case with GLM model <- glm(formula=pa~., data=v) p <- predict(logo, model, cores=2) ## The above does not work with a model from a contributed ## package, as the package needs to be loaded in each core. ## Below are three approaches to deal with that library(randomForest) rfm <- randomForest(formula=pa~., data=v) ## approach 0 (not parallel) rp0 <- predict(logo, rfm) ## approach 1, use the "cpkgs" argument rp1 <- predict(logo, rfm, cores=2, cpkgs="randomForest") ## approach 2, write a custom predict function that loads the package rfun <- function(mod, dat, ...) { library(randomForest) predict(mod, dat, ...) } rp2 <- predict(logo, rfm, fun=rfun, cores=2) ## approach 3, write a parallelized custom predict function rfun <- function(mod, dat, ...) { ncls <- length(cls) nr <- nrow(dat) s <- split(dat, rep(1:ncls, each=ceiling(nr/ncls), length.out=nr)) unlist( parallel::clusterApply(cls, s, function(x, ...) predict(mod, x, ...)) ) } library(parallel) cls <- parallel::makeCluster(2) parallel::clusterExport(cls, c("rfm", "rfun", "randomForest")) rp3 <- predict(logo, rfm, fun=rfun) parallel::stopCluster(cls) plot(c(rp0, rp1, rp2, rp3)) ### with two output variables (probabilities for each class) v$pa <- as.factor(v$pa) rfm2 <- randomForest(formula=pa~., data=v) rfp <- predict(logo, rfm2, cores=2, type="prob", cpkgs="randomForest") } } \keyword{methods} \keyword{spatial} terra/man/sbar.Rd0000644000175000017500000000417014201035750013511 0ustar nileshnilesh\name{sbar} \alias{sbar} \title{scale bar} \description{ Add a scale bar to a map } \usage{ sbar(d, xy=NULL, type="line", divs=2, below="", lonlat=NULL, label, adj=c(0.5, -1), lwd=2, xpd=TRUE, ...) } \arguments{ \item{d}{numeric. Distance covered by the scale bar. For the scale bar, it should be in the units of the coordinates of the plot (map), and in km for angular (longitude/latitude) data; see argument \code{lonlat}. It can also be missing} \item{xy}{numeric. x and y coordinate to place the scale bar. It can also be one of following character values: "bottomleft", "bottom", "bottomright", topleft", "top", "topright", "left", "right", or NULL} \item{type}{for \code{sbar}: "line" or "bar"} \item{divs}{number of divisions for a bar: 2 or 4} \item{below}{character. Text to go below the scale bar (e.g., "kilometers")} \item{lonlat}{logical or NULL. If logical, \code{TRUE} indicates if the plot is using longitude/latitude coordinates. If \code{NULL} this is guessed from the plot's coordinates} \item{label}{vector of three numbers to label the scale bar (beginning, midpoint, end)} \item{adj}{adjustment for text placement} \item{lwd}{line width for the "line" type of the scale bar} \item{xpd}{logical. If \code{TRUE}, the scale bar can be outside the plotting area} \item{...}{graphical arguments to be passed to other methods } } \value{ none } \seealso{ \code{\link[terra]{north}}, \code{\link[terra]{plot}}, \code{\link[terra]{inset}} } \examples{ f <- system.file("ex/meuse.tif", package="terra") r <- rast(f) plot(r) sbar() sbar(1000, xy=c(178500, 333500), type="bar", divs=4, cex=.8) sbar(1000, xy="bottomright", divs=4, cex=.8) north(d=250, c(178550, 332500)) f <- system.file("ex/elev.tif", package="terra") r <- rast(f) plot(r, type="interval") sbar(20, c(6.2, 50.1), type="bar", cex=.8, divs=4) sbar(15, c(6.3, 50), type="bar", below="km", label=c(0,7.5,15), cex=.8) sbar(15, c(6.65, 49.8), cex=.8, label=c(0,"km",15)) north(type=2) sbar(15, c(6.65, 49.7), cex=.8, label="15 kilometer", lwd=5) sbar(15, c(6.65, 49.6), divs=4, cex=.8, below="km") } \keyword{spatial} terra/man/scatter.Rd0000644000175000017500000000255014201035750014227 0ustar nileshnilesh\name{scatterplot} \docType{methods} \alias{plot,SpatRaster,SpatRaster-method} \title{Scatterplot of two SpatRaster layers} \description{ Scatterplot of the values of two SpatRaster layers } \usage{ \S4method{plot}{SpatRaster,SpatRaster}(x, y, maxcell=100000, warn=TRUE, nc, nr, maxnl=16, gridded=FALSE, ncol=25, nrow=25, ...) } \arguments{ \item{x}{SpatRaster} \item{y}{SpatRaster} \item{maxcell}{positive integer. Maximum number of cells to use for the plot} \item{nc}{positive integer. Optional. The number of columns to divide the plotting device in (when plotting multiple layers)} \item{nr}{positive integer. Optional. The number of rows to divide the plotting device in (when plotting multiple layers)} \item{maxnl}{positive integer. Maximum number of layers to plot (for multi-layer objects)} \item{gridded}{logical. If \code{TRUE} the scatterplot is gridded (counts by cells)} \item{warn}{boolean. Show a warning if a sample of the pixels is used (for scatterplot only)} \item{ncol}{positive integer. Number of columns for gridding} \item{nrow}{positive integer. Number of rows for gridding} \item{...}{additional graphical arguments} } \examples{ s <- rast(system.file("ex/logo.tif", package="terra")) plot(s[[1]], s[[2]]) plot(s, sqrt(s[[3:1]])) } \keyword{methods} \keyword{spatial} terra/man/vrt.Rd0000644000175000017500000000175314201035750013401 0ustar nileshnilesh\name{vrt} \docType{methods} \alias{vrt} \alias{vrt,character-method} \title{Virtual Raster Tiles} \description{ Create a Virtual Raster Tiles (VRT) dataset from a collection of file-based raster datasets. } \usage{ \S4method{vrt}{character}(x, filename="", overwrite=FALSE) } \arguments{ \item{x}{character. Filenames of raster "tiles". See \code{\link{tiles}}} \item{filename}{character. Output VRT filename} \item{overwrite}{logical. Should \code{filename} be overwritten if it exists?} } \value{ SpatRaster } \seealso{ \code{\link{makeTiles}} to create tiles; \code{\link{makeVRT}} to create a .vrt file for a file without a header } \examples{ r <- rast(ncols=100, nrows=100) values(r) <- 1:ncell(r) x <- rast(ncols=2, nrows=2) filename <- paste0(tempfile(), "_.tif") ff <- makeTiles(r, x, filename) ff vrtfile <- paste0(tempfile(), ".vrt") v <- vrt(ff, vrtfile) head(readLines(vrtfile)) v } \keyword{methods} \keyword{spatial} terra/man/focalCpp.Rd0000644000175000017500000000615214202260373014315 0ustar nileshnilesh\name{focalCpp} \alias{focalCpp} \alias{focalCpp,SpatRaster-method} \title{Compute focal values with an iterating C++ function} \description{ Calculate focal values with a C++ function that iterates over cells to speed up computations by avoiding an R loop (with apply). See \code{\link{focal}} for an easier to use method. } \usage{ \S4method{focalCpp}{SpatRaster}(x, w=3, fun, ..., fillvalue=NA, silent=TRUE, filename="", overwrite=FALSE, wopt=list()) } \arguments{ \item{x}{SpatRaster} \item{w}{window. The window can be defined as one (for a square) or two numbers (row, col); or with an odd-sized weights matrix. See the Details section in \code{\link{focal}}} \item{fun}{\code{\link{cppFunction}} that iterates over cells. For C++ functions that operate on a single focal window, or for R functions use \code{\link{focal}} instead. The function must have at least three arguments. The first argument can have any name, but it must be a \code{Rcpp::NumericVector}, \code{Rcpp::IntegerVector} or a \code{std::vector}. This is the container that receives the focal values. The other two arguments \code{ni} and \code{wi} must be of type \code{size_t}. \code{ni} represents the number of cells and \code{nw} represents the size of (number of elements in) the window} \item{...}{additional arguments to \code{fun}} \item{fillvalue}{numeric. The value of the cells in the virtual rows and columns outside of the raster} \item{silent}{logical. If \code{TRUE} error messages are printed that may occur when trying \code{fun} to determine the length of the returned value. This can be useful in debugging a \code{fun} that does not work} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{SpatRaster} \seealso{ \code{\link{focal}}, \code{\link{focalValues}} } \examples{ \dontrun{ library(Rcpp) cppFunction( 'NumericVector sum_and_multiply(NumericVector x, double m, size_t ni, size_t nw) { NumericVector out(ni); // loop over cells size_t start = 0; for (size_t i=0; i 1}, a 'parallel' package cluster with that many cores is created. Ignored for C++ level implemented functions "mean", "max", "min", "median", "sum" and "modal"} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{list with named options for writing files as in \code{\link{writeRaster}}} \item{by}{character. The variable used to aggregate the geometries} \item{dissolve}{logical. Should borders between aggregated geometries be dissolved?} } \details{ Aggregation starts at the upper-left end of a SpatRaster. If a division of the number of columns or rows with \code{factor} does not return an integer, the extent of the resulting SpatRaster will be somewhat larger then that of the original SpatRaster. For example, if an input SpatRaster has 100 columns, and \code{fact=12}, the output SpatRaster will have 9 columns and the maximum x coordinate of the output SpatRaster is also adjusted. The function \code{fun} should take multiple numbers, and return a single number. For example \code{mean}, \code{modal}, \code{min} or \code{max}. It should also accept a \code{na.rm} argument (or ignore it as one of the 'dots' arguments). } \seealso{\code{\link{disagg}} to disaggregate} \value{ SpatRaster } \examples{ r <- rast() # aggregated SpatRaster, no values ra <- aggregate(r, fact=10) values(r) <- runif(ncell(r)) # aggregated raster, max of the values ra <- aggregate(r, fact=10, fun=max) # multiple layers s <- c(r, r*2) x <- aggregate(s, 20) ## SpatVector f <- system.file("ex/lux.shp", package="terra") v <- vect(f) va <- aggregate(v, "ID_1") plot(va, "NAME_1", lwd=5, plg=list(x="topright"), mar=rep(2,4)) lines(v, lwd=3, col="light gray") lines(va) text(v, "ID_1", halo=TRUE) } \keyword{methods} \keyword{spatial} terra/man/vect.Rd0000644000175000017500000001065114201035750013524 0ustar nileshnilesh\name{vect} \docType{methods} \alias{vect} \alias{vect,character-method} \alias{vect,list-method} \alias{vect,data.frame-method} \alias{vect,matrix-method} \alias{vect,missing-method} \alias{vect,Spatial-method} \alias{vect,sf-method} \alias{vect,sfc-method} \alias{vect,XY-method} \alias{vect,PackedSpatVector-method} \title{Create SpatVector objects} \description{ Methods to create a SpatVector from a filename or other R object. A filename can be for a shapefile or any spatial file format. You can use a data.frame to make a SpatVector of points; or a "geom" matrix to make a SpatVector of any supported geometry (see examples and \code{\link{geom}}). You can supply a list of SpatVectors to append them into a single SpatVector. SpatVectors can also be created from "Well Known Text", and from spatial vector data objects defined in the \code{sf} or \code{sp} packages. } \usage{ \S4method{vect}{character}(x, layer="", query="", extent=NULL, filter=NULL, crs="", proxy=FALSE) \S4method{vect}{matrix}(x, type="points", atts=NULL, crs="") \S4method{vect}{data.frame}(x, geom=c("lon", "lat"), crs="") \S4method{vect}{list}(x) \S4method{vect}{sf}(x) } \arguments{ \item{x}{character. A filename; or a "Well Known Text" string; or a data.frame (only to make a SpatVector of points); or a "geom" matrix to make a SpatVector of any supported geometry (see examples and \code{\link{geom}}); or a spatial vector data object defined in the \code{sf} or \code{sp} packages} \item{layer}{character. layer name to select a layer from a file (database) with multiple layers} \item{query}{character. An query to subset the dataset in the \href{https://gdal.org/user/ogr_sql_dialect.html}{OGR-SQL dialect}} \item{extent}{Spat* object. The extent of the object is used as a spatial filter to select the geometries to read. Ignored if \code{filter} is not \code{NULL}} \item{filter}{SpatVector. Used as a spatial filter to select geometries to read (the convex hull is used for lines or points)} \item{type}{character. Geometry type. Must be "points", "lines", or "polygons"} \item{atts}{data.frame with the attributes. The number of rows must match the number of geometrical elements} \item{crs}{character. The coordinate reference system in one of the following formats: WKT/WKT2, :, or PROJ-string notation (see \code{\link{crs}})} \item{proxy}{logical. If \code{TRUE} a SpatVectorProxy is returned} \item{geom}{the field name(s) with the geometry data. Either two names for x and y coordinates of points, or a single name for a single column with WKT geometries)} } \seealso{\code{\link{geom}}} \value{SpatVector} \examples{ ### SpatVector from file f <- system.file("ex/lux.shp", package="terra") f v <- vect(f) v ## subsetting (large) files ## with attribute query v <- vect(f, query="SELECT NAME_1, NAME_2, ID_2 FROM lux WHERE ID_2 < 4") v ## with an extent e <- ext(5.9, 6.3, 49.9, 50) v <- vect(f, extent=e) ## with polygons p <- as.polygons(e) v <- vect(f, filter=p) ### SpatVector from a geom matrix x1 <- rbind(c(-180,-20), c(-140,55), c(10, 0), c(-140,-60)) x2 <- rbind(c(-10,0), c(140,60), c(160,0), c(140,-55)) x3 <- rbind(c(-125,0), c(0,60), c(40,5), c(15,-45)) hole <- rbind(c(80,0), c(105,13), c(120,2), c(105,-13)) z <- rbind(cbind(object=1, part=1, x1, hole=0), cbind(object=2, part=1, x3, hole=0), cbind(object=3, part=1, x2, hole=0), cbind(object=3, part=1, hole, hole=1)) colnames(z)[3:4] <- c('x', 'y') p <- vect(z, "polygons") p z[z[, "hole"]==1, "object"] <- 4 lns <- vect(z[,1:4], "lines") plot(p) lines(lns, col="red", lwd=2) ### from wkt v <- vect("POLYGON ((0 -5, 10 0, 10 -10, 0 -5))") wkt <- c("MULTIPOLYGON ( ((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35),(30 20, 20 15, 20 25, 30 20)))", "POLYGON ((0 -5, 10 0, 10 -10, 0 -5))") w <- vect(wkt) # combine two SpatVectors vw <- rbind(w, v) # add a data.frame d <- data.frame(id=1:2, name=c("a", "b")) values(w) <- d # add data.frame on creation, here from a geom matrix g <- geom(w) d <- data.frame(id=1:2, name=c("a", "b")) m <- vect(g, "polygons", atts=d, crs="+proj=longlat +datum=WGS84") ### SpatVector from a data.frame d$wkt <- wkt x <- vect(d, geom="wkt") d$wkt <- NULL d$lon <- c(0,10) d$lat <- c(0,10) x <- vect(d, geom=c("lon", "lat")) # SpatVector to sf #sf::st_as_sf(x) } \keyword{methods} \keyword{spatial} terra/man/init.Rd0000644000175000017500000000313114201035750013521 0ustar nileshnilesh\name{initialize} \alias{init} \alias{init,SpatRaster-method} \title{Initialize a SpatRaster with values} \description{ Create a SpatRaster with values reflecting a cell property: 'x', 'y', 'col', 'row', 'cell' or 'chess'. Alternatively, a function can be used. In that case, cell values are initialized without reference to pre-existing values. E.g., initialize with a random number (\code{fun=\link{runif}}). While there are more direct ways of achieving this for small objects (see examples) for which a vector with all values can be created in memory, the \code{init} function will also work for SpatRaster objects with many cells. } \usage{ \S4method{init}{SpatRaster}(x, fun, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{fun}{function to be applied. This must be a either single number, multiple numbers, a function, or one of a set of known character values. A function must take the number of cells as a single argument to return a vector of values with a length equal to the number of cells, such as \code{fun=runif}. Allowed character values are 'x', 'y', 'row', 'col', 'cell', and 'chess' to get the x or y coordinate, row, col or cell number or a chessboard pattern (alternating 0 and 1 values)} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \examples{ r <- rast(ncols=10, nrows=5, xmin=0, xmax=10, ymin=0, ymax=5) x <- init(r, fun="cell") y <- init(r, fun=runif) # initialize with a single value z <- init(r, fun=8) } \keyword{spatial} terra/man/voronoi.Rd0000644000175000017500000000241014201035750014250 0ustar nileshnilesh\name{voronoi} \alias{delauny} \alias{voronoi} \alias{voronoi,SpatVector-method} \alias{delauny,SpatVector-method} \title{Voronoi diagram and Delauny triangles} \description{ Get a voronoi diagram or delauny triangles for points, or the nodes of lines or polygons } \usage{ \S4method{voronoi}{SpatVector}(x, bnd=NULL, tolerance=0, as.lines=FALSE, deldir=FALSE) \S4method{delauny}{SpatVector}(x, tolerance=0, as.lines=FALSE) } \arguments{ \item{x}{SpatVector} \item{bnd}{SpatVector to set the outer boundary of the voronoi diagram} \item{tolerance}{numeric >= 0, snapping tolerance (0 is no snapping)} \item{as.lines}{logical. If \code{TRUE}, lines are returned without the outer boundary} \item{deldir}{logical. If \code{TRUE}, the \code{\link[deldir]{deldir}} is used instead of the GEOS C++ library method. It has been reported that \code{deldir} does not choke on very large data sets} } \value{SpatVector} \examples{ wkt <- c("MULTIPOLYGON ( ((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35),(30 20, 20 15, 20 25, 30 20)))", "POLYGON ((0 -5, 10 0, 10 -10, 0 -5))") x <- vect(wkt) v <- voronoi(x) v plot(v, lwd=2, col=rainbow(15)) lines(x, col="gray", lwd=2) points(x) } \keyword{spatial} terra/man/selectRange.Rd0000644000175000017500000000322114201035750015012 0ustar nileshnilesh\name{selectRange} \alias{selectRange} \alias{selectRange,SpatRaster-method} \title{Select the values of a range of layers, as specified by cell values in another SpatRaster} \description{ Use a single layer SpatRaster to select cell values from different layers in a multi-layer SpatRaster. The values of the SpatRaster to select layers (\code{y}) should be whole numbers between \code{1} and \code{nlyr(x)} (values outside this range are ignored). See \code{\link{rapp}} for applying af function to a range of variable size. See \code{\link{extract}} for extraction of values by cell, point, or otherwise. } \usage{ \S4method{selectRange}{SpatRaster}(x, y, z=1, repint=0, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{y}{SpatRaster. Cell values must be positive integers. They indicate the first layer to select for each cell} \item{z}{positive integer. The number of layers to select} \item{repint}{integer > 1 and < nlyr(x) allowing for repeated selection at a fixed interval. For example, if \code{x} has 36 layers, and the value of a cell in \code{y}=2 and \code{repint} = 12, the values for layers 2, 14 and 26 are returned} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{\code{\link{rapp}}, \code{\link{tapp}}, \code{\link{extract}}} \examples{ r <- rast(ncols=10, nrows=10) values(r) <- 1 s <- c(r, r+2, r+5) s <- c(s, s) set.seed(1) values(r) <- sample(3, ncell(r), replace=TRUE) x <- selectRange(s, r) x <- selectRange(s, r, 3) } \keyword{methods} \keyword{spatial} terra/man/replace-vector.Rd0000644000175000017500000000224314201035750015474 0ustar nileshnilesh\name{vector-attributes} \alias{$} \alias{$<-} \alias{$,SpatVector-method} \alias{$<-,SpatVector-method} \alias{[[,SpatVector,numeric,missing-method} \alias{[[,SpatVector,logical,missing-method} \alias{[[,SpatVector,character,missing-method} \alias{[[<-,SpatVector,character,missing-method} \alias{[[<-,SpatVector,numeric,missing-method} \alias{[<-,SpatVector,ANY,ANY-method} \alias{[<-,SpatVector,ANY,missing-method} \alias{[<-,SpatVector,missing,ANY-method} \title{Get or replace attribute values of a SpatVector} \description{ Replace values of a SpatVector. } \usage{ \S4method{$}{SpatVector}(x, name) \S4method{$}{SpatVector}(x, name)<-value } \arguments{ \item{x}{SpatVector} \item{name}{character (field name) or numeric (column number} \item{value}{vector of new values} } \value{ vector } \seealso{ \code{\link{values}} } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) v$NAME_1 v$NAME_1[3] <- "my name" v$ID_1 <- LETTERS[1:12] v$new <- sample(12) values(v) v[2,2] <- "hello" v[1,] <- v[10,] v[,3] <- v[,1] v[2, "NAME_2"] <- "terra" head(v, 3) } \keyword{ spatial } terra/man/weighted.mean.Rd0000644000175000017500000000256014201035750015302 0ustar nileshnilesh\name{weighted.mean} \alias{weighted.mean} \alias{weighted.mean,SpatRaster,numeric-method} \alias{weighted.mean,SpatRaster,SpatRaster-method} \title{Weighted mean of layers} \description{ Compute the weighted mean for each cell of the layers of a SpatRaster. The weights can be spatially variable or not. } \usage{ \S4method{weighted.mean}{SpatRaster,numeric}(x, w, na.rm=FALSE, filename="", ...) \S4method{weighted.mean}{SpatRaster,SpatRaster}(x, w, na.rm=FALSE, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{w}{A vector of weights (one number for each layer), or for spatially variable weights, a SpatRaster with weights (should have the same extent, resolution and number of layers as x)} \item{na.rm}{Logical. Should missing values be removed?} \item{filename}{character. Output filename} \item{...}{options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{ \code{\link{Summary-methods}}, \code{\link[stats]{weighted.mean}} } \examples{ b <- rast(system.file("ex/logo.tif", package="terra")) # give least weight to first layer, most to last layer wm1 <- weighted.mean(b, w=1:3) # spatially varying weights # weigh by column number w1 <- init(b, "col") # weigh by row number w2 <- init(b, "row") w <- c(w1, w2, w2) wm2 <- weighted.mean(b, w=w) } terra/man/as.character.Rd0000644000175000017500000000102714201035747015124 0ustar nileshnilesh\name{as.character} \docType{methods} \alias{as.character,SpatExtent-method} \alias{as.character,SpatRaster-method} \title{Create a text representation of (the skeleton of) an object} \description{ Create a text representation of (the skeleton of) an object } \usage{ \S4method{as.character}{SpatExtent}(x) \S4method{as.character}{SpatRaster}(x) } \arguments{ \item{x}{SpatRaster} } \value{ character } \examples{ r <- rast() ext(r) ext(c(0, 20, 0, 20)) } \keyword{spatial} terra/man/animate.Rd0000644000175000017500000000207514201035747014210 0ustar nileshnilesh\name{animate} \docType{methods} \alias{animate} \alias{animate,SpatRaster-method} \title{Animate a SpatRaster} \description{ Animate (sequentially plot) the layers of a SpatRaster to create a movie } \usage{ \S4method{animate}{SpatRaster}(x, pause=0.25, main, range, maxcell=50000, n=1, ...) } \arguments{ \item{x}{SpatRaster} \item{pause}{numeric. How long should be the pause be between layers?} \item{main}{title for each layer. If not supplied the z-value is used if available. Otherwise the names are used.} \item{range}{numeric vector of length 2. Range of values to plot} \item{maxcell}{integer > 0. Maximum number of cells to use for the plot. If \code{maxcell < ncell(x)}, \code{spatSample(type="regular")} is used before plotting} \item{n}{integer > 0. Number of loops} \item{...}{Additional arguments passed to \code{\link{plot}}} } \value{ None } \seealso{ \code{\link{plot}}} \examples{ s <- rast(system.file("ex/logo.tif", package="terra")) animate(s, n=1) } \keyword{methods} \keyword{spatial} terra/man/adjacent.Rd0000644000175000017500000000526614201035747014350 0ustar nileshnilesh\name{adjacent} \docType{methods} \alias{adjacent} \alias{adjacent,SpatRaster-method} \alias{adjacent,SpatVector-method} \title{Adjacent cells} \description{ Identify cells that are adjacent to a set of raster cells. Or identify adjacent polygons } \usage{ \S4method{adjacent}{SpatRaster}(x, cells, directions="rook", pairs=FALSE, include=FALSE) \S4method{adjacent}{SpatVector}(x, type="rook", pairs=TRUE, symmetrical=FALSE) } \arguments{ \item{x}{SpatRaster} \item{cells}{vector of cell numbers for which adjacent cells should be found. Cell numbers start with 1 in the upper-left corner and increase from left to right and from top to bottom} \item{directions}{character or matrix to indicated the directions in which cells are considered connected. The following character values are allowed: "rook" or "4" for the horizontal and vertical neighbors; "bishop" to get the diagonal neighbors; "queen" or "8" to get the vertical, horizontal and diagonal neighbors; or "16" for knight and one-cell queen move neighbors. If \code{directions} is a matrix it should have odd dimensions and have logical (or 0, 1) values} \item{pairs}{logical. If \code{TRUE}, a two-column matrix of pairs of adjacent cells is returned. If \code{x} is a \code{SpatRaster} and \code{pairs} is \code{FALSE}, an \code{n*m} matrix is returned where the number of rows \code{n} is \code{length(cells)} and the number of columns \code{m} is the number of neighbors requested with \code{directions}} \item{include}{logical. Should the focal cells be included in the result? They are always included if \code{pairs=TRUE}} \item{type}{character. One of "rook", "queen", "touches", or "intersects". "queen" and "touches" are synonyms. "rook" exclude polygons that touch at a single node only. "intersects" includes polygons that touch or overlap} \item{symmetrical}{logical. If \code{TRUE}, an adjacent pair is only included once. For example, if polygon 1 is adjacent to polygon 3, the implied adjacency between 3 and 1 is not reported} } \seealso{\code{\link{relate}}, \code{\link{nearby}}} \value{ matrix } \examples{ r <- rast(nrows=10, ncols=10) adjacent(r, cells=c(1, 5, 55), directions="queen") r <- rast(nrows=10, ncols=10, crs="+proj=utm +zone=1 +datum=WGS84") adjacent(r, cells=11, directions="rook") #same as rk <- matrix(c(0,1,0,1,0,1,0,1,0), 3, 3) adjacent(r, cells=11, directions=rk) ## note that with global lat/lon data the E and W connect r <- rast(nrows=10, ncols=10, crs="+proj=longlat +datum=WGS84") adjacent(r, cells=11, directions="rook") f <- system.file("ex/lux.shp", package="terra") v <- vect(f) a <- adjacent(v, symmetrical=TRUE) head(a) } \keyword{spatial} terra/man/add.Rd0000644000175000017500000000114014201035747013312 0ustar nileshnilesh\name{add} \docType{methods} \alias{add<-} \alias{add<-,SpatRaster,SpatRaster-method} \title{Add (in place) a SpatRaster to another SpatRaster object} \description{ Add (in place) a SpatRaster to another SpatRaster object. Comparable with \code{\link{c}}, but withouth copying the object. } \usage{ \S4method{add}{SpatRaster,SpatRaster}(x)<-value } \arguments{ \item{x}{SpatRaster} \item{value}{SpatRaster} } \seealso{\code{\link{c}}} \value{ SpatRaster } \examples{ r <- rast(nrows=5, ncols=9, vals=1:45) x <- c(r, r*2) add(x) <- r*3 x } \keyword{spatial} terra/man/lines.Rd0000644000175000017500000000410014201035750013665 0ustar nileshnilesh\name{lines} \docType{methods} \alias{points} \alias{lines} \alias{polys} \alias{lines,SpatVector-method} \alias{lines,SpatRaster-method} \alias{polys,SpatVector-method} \alias{points,SpatVector-method} \alias{polys,SpatExtent-method} \alias{lines,SpatExtent-method} \alias{points,SpatExtent-method} \title{Add SpatVector data to a map} \description{ Add SpatVector data to a plot (map) with \code{points}, \code{lines}, or \code{polys}. These are simpler alternatives for \code{\link[terra:plot]{plot(x, add=TRUE)}} } \usage{ \S4method{points}{SpatVector}(x, col, cex=1, pch=20, alpha=1, ...) \S4method{lines}{SpatVector}(x, y=NULL, col, lwd=1, lty=1, arrows=FALSE, alpha=1, ...) \S4method{polys}{SpatVector}(x, col, border="black", lwd=1, lty=1, alpha=1, ...) \S4method{points}{SpatExtent}(x, col="black", alpha=1, ...) \S4method{lines}{SpatExtent}(x, col="black", alpha=1, ...) \S4method{polys}{SpatExtent}(x, col, alpha=1, ...) } \arguments{ \item{x}{SpatVector or SpatExtent} \item{y}{missing or SpatVector. If both \code{x} and \code{y} have point geometry and the same number of rows, lines are drawn between pairs of points} \item{col}{character. Colors} \item{border}{character. color(s) of the polygon borders. Use \code{NULL} or \code{NA} to not draw a border} \item{cex}{numeric. point size magnifier. See \code{\link{par}}} \item{pch}{positive integer, line type. See \code{\link{points}}} \item{alpha}{number between 0 and 1 to set transparency} \item{lwd}{numeric, line-width. See \code{\link{par}}} \item{lty}{positive integer, line type. See \code{\link{par}}} \item{arrows}{logical. If \code{TRUE} and \code{y} is a SpatVector, arrows are drawn intead of lines. See \code{?\link{arrows}} for additional arguments} \item{...}{additional graphical arguments such as \code{lwd}, \code{cex} and \code{pch}} } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) r <- rast(v) values(r) <- 1:ncell(r) plot(r) lines(v) points(v) } \keyword{methods} \keyword{spatial} terra/man/RGB.Rd0000644000175000017500000000473614201263127013205 0ustar nileshnilesh\name{RGB} \docType{methods} \alias{RGB} \alias{RGB,SpatRaster-method} \alias{RGB<-} \alias{RGB<-,SpatRaster-method} \alias{colorize} \alias{colorize,SpatRaster-method} \alias{RGB2col} \alias{RGB2col,SpatRaster-method} \title{Layers representing colors} \description{ With \code{RGB} you can get or set the layers to be used as Red, Green and Blue when plotting a SpatRaster. Currently, a benefit of this is that \code{\link[terra]{plot}} will send the object to \code{\link{plotRGB}} With \code{colorize} you can convert a three-layer RGB SpatRaster into other color spaces. You can also convert it into a single-layer SpatRaster with a color-table. } \usage{ \S4method{RGB}{SpatRaster}(x) \S4method{RGB}{SpatRaster}(x)<-value \S4method{colorize}{SpatRaster}(x, to="hsv", alpha=FALSE, stretch=NULL, grays=FALSE, NAzero=FALSE, filename="", overwrite=FALSE, ...) } \arguments{ \item{x}{SpatRaster} \item{value}{vector of three (or four) positive integers indicating the layers that are red, green and blue (and optionally a fourth transparancy layer). Or \code{NULL} to remove the RGB settings} \item{to}{character. The color space to transform the values to. If \code{x} has RGB set, you can transform these to "hsv", "hsi" and "hsl", or use "col" to create a single layer with a color table. You can also use "rgb" to backtransform to RGB} \item{alpha}{logical. Should an alpha (transparancy) channel be included? Only used if \code{x} has a color-table and \code{to="rgb"}} \item{stretch}{character. Option to stretch the values to increase contrast: "lin" (linear) or "hist" (histogram). Only used for transforming RGB to col} \item{grays}{logical. If \code{TRUE}, a gray-scale color-table is created. Only used for transforming RGB to col} \item{NAzero}{logical. If \code{TRUE}, NAs are treated as zeros such that a color can be returned if at least one of the three channels has a value. Only used for transforming RGB to (\code{"col"})} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \examples{ r <- rast(system.file("ex/logo.tif", package="terra")) plot(r) RGB(r) <- NULL plot(r) RGB(r) <- c(3,1,2) plot(r) RGB(r) <- 1:3 x <- colorize(r, "col") y <- colorize(r, "hsv") z <- colorize(y, "rgb") } \keyword{methods} \keyword{spatial} terra/man/all.equal.Rd0000644000175000017500000000312314201035747014443 0ustar nileshnilesh\name{all.equal} \docType{methods} \alias{all.equal} \alias{all.equal,SpatRaster,SpatRaster-method} \title{Compare two SpatRasters for equality} \description{ Compare two SpatRasters for (near) equality. First the attributes of the objects are compared. If these are the same, a (perhaps small) sample of the raster cells is compared as well. The sample size used can be increased with the \code{maxcell} argument. You can set it to \code{Inf}, but for large rasters your computer may not have sufficient memory. See the examples for a safe way to compare all values. } \usage{ \S4method{all.equal}{SpatRaster,SpatRaster}(target, current, maxcell=10000, ...) } \arguments{ \item{target}{SpatRaster} \item{current}{SpatRaster} \item{maxcell}{postive integer. The size of the regular sample used to compare cell values} \item{...}{additional arguments passed to all.equal.numeric to compare cell values} } \seealso{\code{\link{compareGeom}}} \value{ Either \code{TRUE} or a chracter vector describing the differences between target and current. } \examples{ x <- sqrt(1:100) mat <- matrix(x, 10, 10) r1 <- rast(nrows=10, ncols=10, xmin=0, vals = x) r2 <- rast(nrows=10, ncols=10, xmin=0, vals = mat) all.equal(r1, r2) all.equal(r1, r1*1) all.equal(rast(r1), rast(r2)) # compare geometries compareGeom(r1, r2) # Compare all cell values for near equality # as floating point number imprecision can be a problem m <- minmax(r1 - r2) all(abs(m) < 1e-7) # comparison of cell values to create new SpatRaster e <- r1 == r2 } \keyword{spatial} terra/man/interpolate.Rd0000644000175000017500000001333314201035750015111 0ustar nileshnilesh\name{Spatial interpolation} \docType{methods} \alias{interpolate} \alias{interpolate,SpatRaster-method} \title{Interpolate} \description{ Make a SpatRaster with interpolated values using a fitted model object of classes such as "gstat" (gstat package) or "Krige" (fields package), or any other model that has location (e.g., "x" and "y", or "longitude" and "latitude") as predictors (independent variables). If x and y are the only predictors, it is most efficient if you provide an empty (no associated data in memory or on file) SpatRaster for which you want predictions. If there are more spatial predictor variables provide these as a SpatRaster in the first argument of the function. If you do not have x and y locations as implicit predictors in your model you should use \code{\link[terra]{predict}} instead. } \usage{ \S4method{interpolate}{SpatRaster}(object, model, fun=predict, ..., xyNames=c("x", "y"), factors=NULL, const=NULL, index = NULL, na.rm=FALSE, filename="", overwrite=FALSE, wopt=list()) } \arguments{ \item{object}{SpatRaster} \item{model}{model object} \item{fun}{function. Default value is "predict", but can be replaced with e.g. "predict.se" (depending on the class of \code{model}), or a custom function (see examples)} \item{...}{additional arguments passed to \code{fun}} \item{xyNames}{character. variable names that the model uses for the spatial coordinates. E.g., \code{c("longitude", "latitude")}} \item{factors}{list with levels for factor variables. The list elements should be named with names that correspond to names in \code{object} such that they can be matched. This argument may be omitted for some models from which the levels can be extracted from the \code{model} object} \item{const}{data.frame. Can be used to add a constant for which there is no SpatRaster for model predictions. This is particularly useful if the constant is a character-like factor value} \item{index}{positive integer or NULL. Allows for selecting of the variable returned if the model returns multiple variables} \item{na.rm}{logical. If \code{TRUE}, cells with \code{NA} values in the predictors are removed from the computation. This option prevents errors with models that cannot handle \code{NA} values. In most other cases this will not affect the output. An exception is when predicting with a model that returns predicted values even if some (or all!) variables are \code{NA} } \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{list with named options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{ \code{\link{predict}}} \examples{ r <- rast(system.file("ex/elev.tif", package="terra")) ra <- aggregate(r, 10) xy <- data.frame(xyFromCell(ra, 1:ncell(ra))) v <- values(ra) i <- !is.na(v) xy <- xy[i,] v <- v[i] \dontrun{ library(fields) tps <- Tps(xy, v) p <- rast(r) # use model to predict values at all locations p <- interpolate(p, tps) p <- mask(p, r) plot(p) ### change "fun" from predict to fields::predictSE to get the TPS standard error ## need to use "rast(p)" to remove the values se <- interpolate(rast(p), tps, fun=predictSE) se <- mask(se, r) plot(se) ### another predictor variable, "e" e <- (init(r, "x") * init(r, "y")) / 100000000 names(e) <- "e" z <- as.matrix(extract(e, xy)[,-1]) ## add as another independent variable xyz <- cbind(xy, z) tps2 <- Tps(xyz, v) p2 <- interpolate(e, tps2, xyOnly=FALSE) ## as a linear coveriate tps3 <- Tps(xy, v, Z=z) ## Z is a separate argument in Krig.predict, so we need a new function ## Internally (in interpolate) a matrix is formed of x, y, and elev (Z) pfun <- function(model, x, ...) { predict(model, x[,1:2], Z=x[,3], ...) } p3 <- interpolate(e, tps3, fun=pfun) #### gstat examples library(gstat) library(sp) data(meuse) ### inverse distance weighted (IDW) r <- rast(system.file("ex/meuse.tif", package="terra")) mg <- gstat(id = "zinc", formula = zinc~1, locations = ~x+y, data=meuse, nmax=7, set=list(idp = .5)) z <- interpolate(r, mg, debug.level=0, index=1) z <- mask(z, r) ## with a model built with an `sf` object you need to provide custom function library(sf) sfmeuse <- st_as_sf(meuse, coords = c("x", "y"), crs=crs(r)) mgsf <- gstat(id = "zinc", formula = zinc~1, data=sfmeuse, nmax=7, set=list(idp = .5)) interpolate_gstat <- function(model, x, crs, ...) { v <- st_as_sf(x, coords=c("x", "y"), crs=crs) p <- predict(model, v, ...) as.data.frame(p)[,1:2] } zsf <- interpolate(r, mgsf, debug.level=0, fun=interpolate_gstat, crs=crs(r), index=1) zsf <- mask(zsf, r) ### kriging ### ordinary kriging v <- variogram(log(zinc)~1, ~x+y, data=meuse) mv <- fit.variogram(v, vgm(1, "Sph", 300, 1)) gOK <- gstat(NULL, "log.zinc", log(zinc)~1, meuse, locations=~x+y, model=mv) OK <- interpolate(r, gOK, debug.level=0) ## universal kriging vu <- variogram(log(zinc)~elev, ~x+y, data=meuse) mu <- fit.variogram(vu, vgm(1, "Sph", 300, 1)) gUK <- gstat(NULL, "log.zinc", log(zinc)~elev, meuse, locations=~x+y, model=mu) names(r) <- "elev" UK <- interpolate(r, gUK, debug.level=0) ## co-kriging gCoK <- gstat(NULL, 'log.zinc', log(zinc)~1, meuse, locations=~x+y) gCoK <- gstat(gCoK, 'elev', elev~1, meuse, locations=~x+y) gCoK <- gstat(gCoK, 'cadmium', cadmium~1, meuse, locations=~x+y) gCoK <- gstat(gCoK, 'copper', copper~1, meuse, locations=~x+y) coV <- variogram(gCoK) plot(coV, type='b', main='Co-variogram') coV.fit <- fit.lmc(coV, gCoK, vgm(model='Sph', range=1000)) coV.fit plot(coV, coV.fit, main='Fitted Co-variogram') coK <- interpolate(r, coV.fit, debug.level=0) plot(coK) } } \keyword{methods} \keyword{spatial} terra/man/trim.Rd0000644000175000017500000000147614201035750013543 0ustar nileshnilesh\name{trim} \alias{trim} \alias{trim,SpatRaster-method} \title{Trim a SpatRaster} \description{ Trim (shrink) a SpatRaster by removing outer rows and columns that are \code{NA} or another value. } \usage{ \S4method{trim}{SpatRaster}(x, padding=0, value=NA, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{padding}{integer. Number of outer rows/columns to keep} \item{value}{numeric. The value of outer rows or columns that are to be removed} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \examples{ r <- rast(ncols=10, nrows=10, xmin=0,xmax=10,ymin=0,ymax=10) v <- rep(NA, ncell(r)) v[c(12,34,69)] <- 1:3 values(r) <- v s <- trim(r) } \keyword{spatial} terra/man/scale.Rd0000644000175000017500000000251014201035750013645 0ustar nileshnilesh\name{scale} \alias{scale} \alias{scale,SpatRaster-method} \title{Scale values} \description{ Center and/or scale raster data. For details see \code{\link{scale}} } \usage{ \S4method{scale}{SpatRaster}(x, center=TRUE, scale=TRUE) } \arguments{ \item{x}{SpatRaster} \item{center}{logical or numeric. If \code{TRUE}, centering is done by subtracting the layer means (omitting \code{NA}s), and if \code{FALSE}, no centering is done. If \code{center} is a numeric vector (recycled to \code{nlyr(x)}), then each layer of \code{x} has the corresponding value from center subtracted from it.} \item{scale}{logical or numeric. If \code{TRUE}, scaling is done by dividing the (centered) layers of \code{x} by their standard deviations if \code{center} is \code{TRUE}, and the root mean square otherwise. If scale is \code{FALSE}, no scaling is done. If \code{scale} is a numeric vector (recycled to \code{nlyr(x)}), each layer of \code{x} is divided by the corresponding value. Scaling is done after centering.} } \value{ SpatRaster } \seealso{ \code{\link[base]{scale}} } \examples{ r <- rast(system.file("ex/logo.tif", package="terra")) s <- scale(r) ## the equivalent, computed in steps m <- global(r, "mean") rr <- r - m[,1] rms <- global(rr, "rms") ss <- rr / rms[,1] } \keyword{ spatial } terra/man/gridDistance.Rd0000644000175000017500000000417514201035750015167 0ustar nileshnilesh\name{gridDistance} \alias{gridDistance} \alias{gridDistance,SpatRaster-method} \title{Distance on a grid} \description{ The function calculates the distance to cells of a SpatRaster when the path has to go through the centers of the eight neighboring raster cells. The distance is in meters if the coordinate reference system (CRS) of the SpatRaster is longitude/latitude (\code{+proj=longlat}) and in the units of the CRS (typically meters) in other cases. Distances are computed by summing local distances between cells, which are connected with their neighbors in 8 directions. } \usage{ \S4method{gridDistance}{SpatRaster}(x, origin, omit=NULL, chunk=FALSE, filename="", overwrite=FALSE, ...) } \arguments{ \item{x}{SpatRaster} \item{origin}{value(s) of the cells from which the distance is calculated. If \code{origin=NULL} all cells that are not \code{NA} are origins} \item{omit}{value(s) of the cells that cannot be traversed (optional)} \item{chunk}{logical. If \code{TRUE} the data are processed in chunks. This may be necessary for large datasets, but could lead to errors in the case of complex areas that need to be omitted if they are spread over different chunks (meandering rivers, for instance).} \item{filename}{character. output filename (optional)} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{...}{additional arguments as for \code{\link{writeRaster}}} } \seealso{See \code{\link[terra]{distance}} for "as the crow flies" distance} \note{ If the SpatRaster to be processed is big, it will be processed in chunks. This may lead to errors in the case of complex objects that cannot be traversed are spread over different chunks (meandering rivers, for instance). } \value{SpatRaster} \author{Jacob van Etten and Robert J. Hijmans } \examples{ #world lon/lat raster r <- rast(ncol=10,nrow=10, vals=1) r[48] <- 2 r[66:68] <- 3 d <- gridDistance(r,origin=2,omit=3) plot(d) #UTM small area crs(r) <- "+proj=utm +zone=15 +ellps=GRS80 +datum=NAD83 +units=m +no_defs" d <- gridDistance(r,origin=2,omit=3) plot(d) } \keyword{spatial} terra/man/extend.Rd0000644000175000017500000000340314201035750014047 0ustar nileshnilesh\name{extend} \alias{extend} \alias{extend,SpatRaster-method} \alias{extend,SpatExtent-method} \title{Extend} \description{ Enlarge the spatial extent of a SpatRaster. See \code{\link{crop}} if you (also) want to remove rows or columns. You can also enlarge a SpatExtent with this method, or with algebraic notation (see examples) } \usage{ \S4method{extend}{SpatRaster}(x, y, snap="near", filename="", overwrite=FALSE, ...) \S4method{extend}{SpatExtent}(x, y) } \arguments{ \item{x}{SpatRaster or SpatExtent} \item{y}{If \code{x} is a SpatRaster, \code{y} should be a SpatExtent, or an object from which it can be extracted (such as SpatRaster and SpatVector objects). Alternatively, you can provide two positive integers indicating the number of rows and columns that need to be added at each side (or a single positive integer when the number of rows and columns is equal) If \code{x} is a SpatExtent, \code{y} should be a numeric vector of 1, 2, or 4 elements} \item{snap}{character. One of "near", "in", or "out". Used to align \code{y} to the geometry of \code{x}} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster or SpatExtent } \seealso{\code{\link{crop}}, \code{\link{merge}}, \code{\link{ext}}} \examples{ r <- rast(xmin=-150, xmax=-120, ymin=30, ymax=60, ncols=36, nrows=18) values(r) <- 1:ncell(r) e <- ext(-180, -100, 40, 70) re <- extend(r, e) # extend with a number of rows and columns (at each side) re2 <- extend(r, c(2,10)) # SpatExtent e <- ext(r) e extend(e, 10) extend(e, c(10, -10, 0, 20)) } \keyword{spatial} terra/man/writeVector.Rd0000644000175000017500000000310714202623274015103 0ustar nileshnilesh\name{writeVector} \alias{writeVector,SpatVector,character-method} \alias{writeVector} \title{Write SpatVector data to a file} \description{ Write a SpatVector to a file. You can choose one of many file formats. } \usage{ \S4method{writeVector}{SpatVector,character}(x, filename, filetype=NULL, layer=NULL, insert=FALSE, overwrite=FALSE, options="ENCODING=UTF-8") } \arguments{ \item{x}{SpatVector} \item{filename}{character. Output filename} \item{filetype}{character. A file format associated with a GDAL "driver" such as "ESRI Shapefile". See \code{gdal(drivers=TRUE)} or the \href{https://gdal.org/drivers/vector/index.html}{GDAL docs}. If \code{NULL} it is attempted to guess the filetype from the filename extension} \item{layer}{character. Output layer name. If \code{NULL} the filename is used} \item{insert}{logical. If \code{TRUE}, a new layer is inserted into the file, if the format allows it (e.g. GPKG allows that). See \code{\link{vector_layers}} to remove a layer} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{options}{character. Format specific GDAL options such as "ENCODING=UTF-8". Use NULL or "" to not use any options} } \examples{ v <- vect(cbind(1:5,1:5)) crs(v) <- "+proj=longlat +datum=WGS84" v$id <- 1:length(v) v$name <- letters[1:length(v)] tmpf1 <- tempfile() writeVector(v, tmpf1) x <- vect(tmpf1) f <- system.file("ex/lux.shp", package="terra") v <- vect(f) tmpf2 <- tempfile() writeVector(v, tmpf2) y <- vect(tmpf2) } \keyword{ spatial } \keyword{ methods } terra/man/subst.Rd0000644000175000017500000000207414201035750013723 0ustar nileshnilesh\name{subst} \docType{methods} \alias{subst} \alias{subst,SpatRaster-method} \title{replace cell values} \description{ Substitute(replace) cell values of a SpatRaster with a new value. See \code{\link{classify}} for more complex/flexible replacement. } \usage{ \S4method{subst}{SpatRaster}(x, from, to, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{from}{numeric value(s)} \item{to}{numeric value(s). Normally a vector of the same length as `from`. If \code{x} has a single layer, it can also be a matrix of numeric value(s) where \code{nrow(x) == length(from)}. In that case the output has multiple layers, one for each column in \code{to}} \item{filename}{character. Output filename} \item{...}{Additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{\code{\link{classify}}} \examples{ r <- rast(ncols=5, nrows=5, xmin=0, xmax=1, ymin=0, ymax=1, crs="") r <- init(r, 1:6) x <- subst(r, 3, 7) x <- subst(r, 2:3, NA) x <- subst(x, NA, 10) } \keyword{spatial} terra/man/rep.Rd0000644000175000017500000000073514201035750013353 0ustar nileshnilesh\name{rep} \docType{methods} \alias{rep} \alias{rep,SpatRaster-method} \title{Replicate layers} \description{ Replicate layers in a SpatRaster } \usage{ \S4method{rep}{SpatRaster}(x, ...) } \arguments{ \item{x}{SpatRaster} \item{...}{arguments as in \code{\link[base]{rep}}} } \value{ SpatRaster } \examples{ s <- rast(system.file("ex/logo.tif", package="terra")) x <- rep(s, 2) nlyr(x) names(x) x } \keyword{spatial} terra/man/geometry.Rd0000644000175000017500000000350214201035750014413 0ustar nileshnilesh\name{geom} \docType{methods} \alias{geom} \alias{geom,SpatVector-method} \title{Get the geometry (coordinates) of a SpatVector} \description{ Get the geometry of a SpatVector. If \code{wkt=FALSE}, this is a five-column matrix or data.frame: the vector object ID, the IDs for the parts of each object (e.g. five polygons that together are one spatial object), the x (longitude) and y (latitude) coordinates, and a flag indicating whether the part is a "hole" (only relevant for polygons). If \code{wkt=TRUE}, the "well-known text" representation is returned as a character vector. } \usage{ \S4method{geom}{SpatVector}(x, wkt=FALSE, hex=FALSE, df=FALSE) } \arguments{ \item{x}{SpatVector} \item{wkt}{logical. If \code{TRUE} the WKT geometry is returned (unless \code{hex} is also \code{TRUE})} \item{hex}{logical. If \code{TRUE} the hexadecimal geometry is returned} \item{df}{logical. If \code{TRUE} a \code{data.frame} is returned instead of a matrix (only for \code{wkt=FALSE} and \code{hex=FALSE})} } \value{ matrix } \seealso{ See \code{\link{xyFromCell}} to get the coordinates of the cells of a SpatRaster } \examples{ x1 <- rbind(c(-175,-20), c(-140,55), c(10, 0), c(-140,-60)) x2 <- rbind(c(-125,0), c(0,60), c(40,5), c(15,-45)) x3 <- rbind(c(-10,0), c(140,60), c(160,0), c(140,-55)) x4 <- rbind(c(80,0), c(105,13), c(120,2), c(105,-13)) z <- rbind(cbind(object=1, part=1, x1), cbind(object=2, part=1, x2), cbind(object=3, part=1, x3), cbind(object=3, part=2, x4)) colnames(z)[3:4] <- c('x', 'y') z <- cbind(z, hole=0) z[(z[, "object"]==3 & z[,"part"]==2), "hole"] <- 1 p <- vect(z, "polygons") geom(p) f <- system.file("ex/lux.shp", package="terra") v <- vect(f) g <- geom(v) head(g) w <- geom(v, wkt=TRUE) substr(w, 1, 60) } \keyword{spatial} terra/man/project.Rd0000644000175000017500000001157714201035750014241 0ustar nileshnilesh\name{project} \alias{project} \alias{project,SpatVector-method} \alias{project,SpatRaster-method} \title{Change the coordinate reference system} \description{ Change the coordinate reference system ("project") of a SpatVector or SpatRaster. } \usage{ \S4method{project}{SpatVector}(x, y) \S4method{project}{SpatRaster}(x, y, method, mask=FALSE, align=FALSE, gdal=TRUE, filename="", ...) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{y}{if (\code{x} is a SpatRaster, the prefered approach is for \code{y} to be a SpatRaster as well, serving as a template for the geometry (extent and resolution) of the output SpatRaster. Alternatively, you can provide a coordinate reference system (crs) description. You can use the following formats to define coordinate reference systems: WKT, PROJ.4 (e.g., \code{+proj=longlat +datum=WGS84}), or an EPSG code (e.g., \code{"epsg:4326"}). But note that the PROJ.4 notation has been deprecated, and you can only use if with the WGS84/NAD83 and NAD27 datums. Other datums are silently ignored. If \code{x} is a SpatVector, you can provide a crs definition as discussed above, or any other object from which such a crs can be extracted with \code{\link{crs}}} \item{method}{character. Method used for estimating the new cell values of a SpatRaster. One of: \code{near}: nearest neighbor. This method is fast, and it can be the preferred method if the cell values represent classes. It is not a good choice for continuous values. This is used by default if the first layer of \code{x} is categorical. \code{bilinear}: bilinear interpolation. This is the default if the first layer of \code{x} is numeric (not categorical). \code{cubic}: cubic interpolation. \code{cubicspline}: cubic spline interpolation. } \item{mask}{logical. If \code{TRUE}, mask out areas outside the input extent (see example with Robinson projection)} \item{align}{logical. If \code{TRUE}, and \code{y} is a SpatRaster, the template is used for the spatial resolution and origin, but the extent is set such that all of the extent of \code{x} is included} \item{gdal}{logical. If \code{TRUE} the GDAL-warp algorithm is used. Otherwise a slower internal algorithm is used that may be more accurate if there is much variation in the cell sizes of the output raster. Only the \code{near} and \code{bilinear} algorithms are available for the internal algorithm} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatVector or SpatRaster } \seealso{\code{\link{crs}}, \code{\link{resample}}} \note{ User beware. Sadly, the PROJ.4 notation has been partly deprecated in the GDAL/PROJ library that is used by this function. You can still use this notation, but *only* with the the WGS84 datum. Other datums are silently ignored. When printing a Spat* object the PROJ.4 notation is shown because it is the most concise and clear format available. However, internally a WKT representation is used (see \code{\link{crs}}). Transforming (projecting) raster data is fundamentally different from transforming vector data. Vector data can be transformed and back-transformed without loss in precision and without changes in the values. This is not the case with raster data. In each transformation the values for the new cells are estimated in some fashion. Therefore, if you need to match raster and vector data for analysis, you should generally transform the vector data. When using this method with a \code{SpatRaster}, the preferable approach is to provide a template \code{SpatRaster} as argument \code{y}. The template is then another raster dataset that you want your data to align with. If you do not have a template to begin with, you can do \code{project(x, crs)} and then manipulate the output to get the template you want. For example, where possible use whole numbers for the extent and resolution so that you do not have to worry about small differences in the future. You can use commands like \code{dim(z) = c(180, 360)} or \code{res(z) <- 100000}. The output resolution should be similar to the input resolution, but there is not "correct" resolution in raster transformation; but it is not obvious what this resolution is if you are using lon/lat data that spans a large North-South extent. } \examples{ ## SpatRaster a <- rast(ncols=40, nrows=40, xmin=-110, xmax=-90, ymin=40, ymax=60, crs="+proj=longlat +datum=WGS84") values(a) <- 1:ncell(a) newcrs="+proj=lcc +lat_1=48 +lat_2=33 +lon_0=-100 +datum=WGS84" b <- rast(ncols=94, nrows=124, xmin=-944881, xmax=935118, ymin=4664377, ymax=7144377, crs=newcrs) w <- project(a, b) ## SpatVector f <- system.file("ex/lux.shp", package="terra") v <- vect(f) crs <- "+proj=moll +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84" p <- project(v, crs) p } \keyword{spatial} terra/man/rescale.Rd0000644000175000017500000000214714201035750014202 0ustar nileshnilesh\name{rescale} \docType{methods} \alias{rescale} \alias{rescale,SpatRaster-method} \alias{rescale,SpatVector-method} \title{rescale} \description{ Rescale a SpatVector or SpatRaster. This may be useful to make small \code{\link{inset}} maps or for georeferencing. } \usage{ \S4method{rescale}{SpatRaster}(x, fx=0.5, fy=fx, x0, y0) \S4method{rescale}{SpatVector}(x, fx=0.5, fy=fx, x0, y0) } \arguments{ \item{x}{SpatVector or SpatRaster} \item{fx}{numeric > 0. The horizontal scaling factor} \item{fy}{numeric > 0. The vertical scaling factor} \item{x0}{numeric. x-coordinate of the center of rescaling. If missing, the center of the extent of \code{x} is used} \item{y0}{numeric. y-coordinate of the center of rescaling. If missing, the center of the extent of \code{x} is used} } \value{ Same as \code{x} } \seealso{\code{\link{t}}, \code{\link{shift}}, \code{\link{flip}}, \code{\link{rotate}}, \code{\link{inset}}} \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) w <- rescale(v, 0.2) plot(v) lines(w, col="red") } \keyword{spatial} terra/man/fill.Rd0000644000175000017500000000177014201035750013513 0ustar nileshnilesh\name{fillHoles} \docType{methods} \alias{fillHoles} \alias{fillHoles,SpatVector-method} \title{Remove holes from polygons} \description{ Remove the holes in SpatVector polygons. If \code{inverse=TRUE} the holes are returned (as polygons). } \usage{ \S4method{fillHoles}{SpatVector}(x, inverse=FALSE) } \arguments{ \item{x}{SpatVector} \item{inverse}{logical. If \code{TRUE} the holes are returned as polygons} } \value{SpatVector} \examples{ x <- rbind(c(-10,0), c(140,60), c(160,0), c(140,-55)) hole <- rbind(c(80,0), c(105,13), c(120,2), c(105,-13)) z <- rbind(cbind(object=1, part=1, x, hole=0), cbind(object=1, part=1, hole, hole=1)) colnames(z)[3:4] <- c('x', 'y') p <- vect(z, "polygons", atts=data.frame(id=1)) p f <- fillHoles(p) g <- fillHoles(p, inverse=TRUE) plot(p, lwd=16, border="gray", col="light yellow") polys(f, border="blue", lwd=3, density=4, col="orange") polys(g, col="white", lwd=3) } \keyword{methods} \keyword{spatial} terra/man/vector_layers.Rd0000644000175000017500000000111114201035750015433 0ustar nileshnilesh\name{vector_layers} \alias{vector_layers} \title{List or remove layers from a vector file} \description{ List or remove layers from a vector file that supports layers such as GPGK } \usage{ vector_layers(filename, delete="", return_error=FALSE) } \arguments{ \item{filename}{character. filename} \item{delete}{character. layers to be deleted (ignored if the value is \code{""}} \item{return_error}{logical. If \code{TRUE}, an error occurs if some layers cannot be deleted. Otherwise a waring is given} } \keyword{ spatial } \keyword{ methods } terra/man/segregate.Rd0000644000175000017500000000261514201035750014532 0ustar nileshnilesh\name{segregate} \docType{methods} \alias{segregate} \alias{segregate,SpatRaster-method} \title{segregate} \description{ Create a SpatRaster with a layer for each class (value, or subset of the values) in the input SpatRaster. For example, if the input has vegetation types, this function will create a layer (presence/absence; dummy variable) for each of these classes. Classes and cell values are always truncated to integers. This is called "one-hot encoding" or "dummy encoding" (for a dummy encoding scheme you can remove (any) one of the output layers as it is redundant). } \usage{ \S4method{segregate}{SpatRaster}(x, classes=NULL, keep=FALSE, other=0, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{classes}{numeric. The values (classes) for which layers should be made. If \code{NULL} all classes are used} \item{keep}{logical. If \code{TRUE}, cells that are of the class represented by a layer get that value, rather than a value of 1} \item{other}{numeric. Value to assign to cells that are not of the class represented by a layer} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \examples{ r <- rast(nrows=5, ncols=5) values(r) <- rep(c(1:4, NA), each=5) b <- segregate(r) bb <- segregate(r, keep=TRUE, other=NA) } \keyword{spatial} terra/man/rapp.Rd0000644000175000017500000000477414201035750013536 0ustar nileshnilesh\name{rapp} \docType{methods} \alias{rapp} \alias{rapp,SpatRaster-method} \title{Range-Apply} \description{ Apply a function to a range of the layers of a SpatRaster that varies by cell. The range is specified for each cell one or two SpatRasters (arguments \code{first} and \code{last}). For either \code{first} or \code{last} you can use a numeric constant instead. See \code{\link{selectRange}} to create a new SpatRaster by extracting one or more values starting at a cell-varying layer. See \code{\link{app}} or \code{\link{Summary-methods}} if you want to apply a function to all cells (not a range), perhaps after making a \code{\link{subset}} of a SpatRaster. } \usage{ \S4method{rapp}{SpatRaster}(x, first, last, fun, ..., allyrs=FALSE, fill=NA, clamp=FALSE, filename="", overwrite=FALSE, wopt=list()) } \arguments{ \item{x}{SpatRaster} \item{first}{SpatRaster or positive integer between 1 and nlyr(x), indicating the first layer in the range of layers to be considered} \item{last}{SpatRaster or positive integer between 1 and nlyr(x), indicating the last layer in the range to be considered} \item{fun}{function to be applied} \item{...}{additional arguments passed to \code{fun}} \item{allyrs}{logical. Should the values of all layers be passed to \code{fun}. The values outside of the range are set to \code{fill}} \item{fill}{numeric. The fill value for the the values outside of the range, for when \code{allyrs=TRUE}} \item{clamp}{logical. If \code{FALSE} and the specified range is outside \code{1:nlyr(x)} all cells are considered \code{NA}. Otherwise, the invalid part of the range is ignored} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{list with named options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{\code{\link{selectRange}}, \code{\link{app}}, \code{\link{Summary-methods}}, \code{\link{lapp}}, \code{\link{tapp}}} \examples{ r <- rast(ncols=9, nrows=9) values(r) <- 1:ncell(r) s <- c(r, r, r, r, r, r) s <- s * 1:6 s[1:2] <- NA start <- end <- rast(r) start[] <- 1:3 end[] <- 4:6 a <- rapp(s, start, end, fun="mean") b <- rapp(s, start, 2, fun="mean") # cumsum from start to nlyr(x). return all layers r <- rapp(s, start, nlyr(s), cumsum, allyrs=TRUE, fill=0) # return only the final value rr <- rapp(s, start, nlyr(s), function(i) max(cumsum(i))) } \keyword{methods} \keyword{spatial} terra/man/impose.Rd0000644000175000017500000000126314201035750014056 0ustar nileshnilesh\name{impose} \docType{methods} \alias{impose} \alias{impose,SpatRasterCollection-method} \title{ Impose the geometry of a SpatRaster to those in a SpatRasterCollection. } \description{ Warp the members of a SpatRasterCollection to match the geometry of a SpatRaster. } \usage{ \S4method{impose}{SpatRasterCollection}(x, y, filename="", ...) } \arguments{ \item{x}{SpatRasterCollection} \item{y}{SpatRaster} \item{filename}{character. Output filename} \item{...}{list with named options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{ \code{\link{resample}} } \keyword{methods} \keyword{spatial} terra/man/summary.Rd0000644000175000017500000000264614201035750014265 0ustar nileshnilesh\name{summary} \docType{methods} \alias{summary} \alias{summary,SpatRaster-method} \alias{summary,SpatVector-method} \alias{Summary,SpatExtent-method} \alias{Summary,SpatRaster-method} \alias{Summary,SpatVector-method} \title{summary} \description{ Compute summary statistics (min, max, mean, and quartiles) for SpatRaster using base \code{\link[base]{summary}} method. A sample is used for very large files. For single or other statistics see \code{\link{Summary-methods}}, \code{\link{global}}, and \code{\link{quantile}} } \usage{ \S4method{summary}{SpatRaster}(object, size=100000, warn=TRUE, ...) \S4method{summary}{SpatVector}(object, ...) } \arguments{ \item{object}{SpatRaster or SpatVector} \item{size}{positive integer. Size of a regular sample used for large datasets (see \code{\link{spatSample}})} \item{warn}{logical. If \code{TRUE} a warning is given if a sample is used} \item{...}{additional arguments passed on to the base \code{\link[base]{summary} method}} } \value{matrix with (an estimate of) the median, minimum and maximum values, the first and third quartiles, and the number of cells with \code{NA} values} \seealso{ \code{\link{Summary-methods}}, \code{\link{global}}, \code{\link{quantile}} } \examples{ set.seed(0) r <- rast(nrows=10, ncols=10, nlyrs=3) values(r) <- runif(nlyr(r)*ncell(r)) summary(r) } \keyword{methods} \keyword{spatial} terra/man/nearby.Rd0000644000175000017500000000303014201035750014034 0ustar nileshnilesh\name{nearest} \docType{methods} \alias{nearby} \alias{nearby,SpatVector-method} \alias{nearest} \alias{nearest,SpatVector-method} \title{nearby geometries} \description{ Identify geometries that are near to each other. Either get the index of all geometries within a certain distance, or the k nearest neighbors, or (with \code{nearest}) get the nearest points between two geometries. } \usage{ \S4method{nearby}{SpatVector}(x, y=NULL, distance=0, k=1, centroids=TRUE, symmetrical=TRUE) \S4method{nearest}{SpatVector}(x, y, pairs=FALSE, centroids=TRUE, lines=FALSE) } \arguments{ \item{x}{SpatVector} \item{y}{SpatVector or NULL} \item{distance}{numeric. maximum distance} \item{k}{positive integer. number of neighbors. Ignored if \code{distance > 0}} \item{centroids}{logical. Should the centroids of polygons be used?} \item{symmetrical}{logical. If \code{TRUE}, a near pair is only included once. That is, if geometry 1 is near to geometry 3, the implied nearness between 3 and 1 is not reported. Ignored if \code{k} neighbors are returned} \item{pairs}{logical. If \code{TRUE} pairwise nearest points are returned (only relevant when using at least one SpatVector of lines or polygons} \item{lines}{logical. If \code{TRUE} lines between the nearest points instead of (the nearest) points } } \seealso{\code{\link{relate}}, \code{\link{adjacent}}} \value{ matrix } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) nearby(v, distance=12000) } \keyword{spatial} terra/man/names.Rd0000644000175000017500000000471714201035750013674 0ustar nileshnilesh\name{names} \alias{name} \alias{name<-} \alias{names} \alias{names<-} \alias{varnames} \alias{varnames<-} \alias{longnames} \alias{longnames<-} \alias{names,SpatRaster-method} \alias{names<-,SpatRaster-method} \alias{varnames,SpatRaster-method} \alias{varnames<-,SpatRaster-method} \alias{longnames,SpatRaster-method} \alias{longnames<-,SpatRaster-method} \alias{names,SpatRasterDataset-method} \alias{names<-,SpatRasterDataset-method} \alias{varnames,SpatRasterDataset-method} \alias{varnames<-,SpatRasterDataset-method} \alias{longnames,SpatRasterDataset-method} \alias{longnames<-,SpatRasterDataset-method} \alias{names,SpatVector-method} \alias{names,SpatVectorProxy-method} \alias{names<-,SpatVector-method} \title{Names of Spat* objects} \description{ Get or set the names of the layers of a SpatRaster or the attributes of a SpatVector. With \code{longnames} you can get or set the "long names" of a SpatRaster or SpatRasterDataset. For a SpatRaster, you can also get/set a variable name or long name (one per data source). See \code{\link{set.names}} for in-place setting of names. } \usage{ \S4method{names}{SpatRaster}(x) \S4method{names}{SpatRaster}(x)<-value \S4method{varnames}{SpatRaster}(x) \S4method{varnames}{SpatRaster}(x)<-value \S4method{longnames}{SpatRaster}(x) \S4method{longnames}{SpatRaster}(x)<-value \S4method{names}{SpatRasterDataset}(x) \S4method{names}{SpatRasterDataset}(x)<-value \S4method{varnames}{SpatRasterDataset}(x) \S4method{varnames}{SpatRasterDataset}(x)<-value \S4method{longnames}{SpatRasterDataset}(x) \S4method{longnames}{SpatRasterDataset}(x)<-value \S4method{names}{SpatVector}(x) \S4method{names}{SpatVector}(x)<-value } \arguments{ \item{x}{SpatRaster, SpatRasterDataset, or SpatVector} \item{value}{character (vector)} } \value{ character } \note{ terra enforces neither unique nor valid names. See \code{\link{make.unique}} to create unique names and \code{{make.names}} to make syntactically valid names. } \examples{ s <- rast(ncols=5, nrows=5, nlyrs=3) nlyr(s) names(s) names(s) <- c("a", "b", "c") names(s) # space is not valid names(s)[2] <- "hello world" names(s) # two invalid names names(s) <- c("a", " a ", "3") names(s) # SpatVector names f <- system.file("ex/lux.shp", package="terra") v <- vect(f) names(v) names(v) <- paste0(substr(names(v), 1, 2), "_", 1:ncol(v)) names(v) } \keyword{spatial} terra/man/arith-generic.Rd0000644000175000017500000000323414201035747015311 0ustar nileshnilesh\name{Arith-methods} \docType{methods} \alias{Arith-methods} \alias{Arith,SpatExtent,numeric-method} \alias{Arith,numeric,SpatExtent-method} \alias{Arith,SpatExtent,SpatExtent-method} \alias{Arith,SpatRaster,SpatRaster-method} \alias{Arith,SpatVector,SpatVector-method} \alias{Arith,SpatRaster,missing-method} \alias{Arith,numeric,SpatRaster-method} \alias{Arith,SpatRaster,numeric-method} \alias{Arith,missing,SpatRaster-method} \title{Arithmetic} \description{ Standard arithmetic operators for computations with SpatRasters. Computations are local (applied on a cell by cell basis). If multiple SpatRaster objects are used, these must have the same geometry (extent and resolution). These operators have been implemented: \code{ +, -, *, /, ^, \%\%, \%/\% } The following methods have been implemented for \code{SpatExtent}: for \code{(SpatExtent, SpatExtent)}: \code{+, -}, and for \code{(SpatExtent, numeric)}: \code{+, -, *, /, \%\%} } \section{seealso}{ \code{\link{ifel}} to conveniently combine operations and \code{\link{Math-methods}} or \code{\link{app}} to use mathematical functions not implemented by the package. } \value{ SpatRaster or SpatExtent } \examples{ r1 <- rast(ncols=10, nrows=10) v <- runif(ncell(r1)) v[10:20] <- NA values(r1) <- v r2 <- rast(r1) values(r2) <- 1:ncell(r2) / ncell(r2) r3 <- r1 + r2 r2 <- r1 / 10 r3 <- r1 * (r2 - 1 / r2) b <- c(r1, r2, r3) b2 <- b * 10 ### SpatExtent methods x <- ext(0.1, 2.2, 0, 3) y <- ext(-2, 1, -2,2) # union x + y # intersection x * y e <- x %% 2 e e * 2 e / 2 e + 1 e - 1 } \keyword{methods} \keyword{math} \keyword{spatial} terra/man/terraOptions.Rd0000644000175000017500000000305014201035750015247 0ustar nileshnilesh\name{options} \alias{terraOptions} \title{Options} \description{ Class and methods for showing and setting general options for terra. } \usage{ terraOptions(...) } \arguments{ \item{...}{option names and values (see Details). Or missing, to show the current options} } \details{ The following options are available. \bold{memfrac} - value between 0 and 0.9 (larger values give a warning). The fraction of RAM that may be used by the program. \bold{memmax} - the maximum amount of RAM (in GB) that terra can use when processing a raster dataset. Should be less than what is detected (see \code{\link{mem_info}}, and higher values are ignored. Set it to a negative number or NA to not set this option). \code{terraOptions} only shows the value of \code{memmax} it it set. \bold{tempdir} - directory where temporary files are written. The default what is returned by \code{tempdir()}. \bold{datatype} - default data type. See \code{\link{writeRaster}} \bold{todisk} - logical. If \code{TRUE} write all raster data to disk (temp file if no file name is specified). For debugging. \bold{progress} - non-negative integer. A progress bar is shown if the number of chunks in which the data is processed is larger than this number. No progress bar is shown if the value is zero \bold{verbose} - logical. If \code{TRUE} debugging info is printed for some functions } \examples{ terraOptions() terraOptions(memfrac=0.5, tempdir = "c:/temp") terraOptions(progress=10) terraOptions() } \keyword{classes} \keyword{spatial} terra/man/cover.Rd0000644000175000017500000000302614201035750013677 0ustar nileshnilesh\name{cover} \docType{methods} \alias{cover} \alias{cover,SpatRaster,SpatRaster-method} \alias{cover,SpatVector,SpatVector-method} \title{Replace values with values from another object} \description{ Replace \code{NA} or other values in SpatRaster \code{x} with the values of SpatRaster \code{y} For polygons: areas of \code{x} that overlap with \code{y} are replaced by \code{y} or, if \code{identity=TRUE} intersected with \code{y}. } \usage{ \S4method{cover}{SpatRaster,SpatRaster}(x, y, values=NA, filename="", ...) \S4method{cover}{SpatVector,SpatVector}(x, y, identity=FALSE) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{y}{Same as \code{x}} \item{values}{numeric. The cell values in \code{x} to be replaced by the values in \code{y}} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} \item{identity}{logical. If \code{TRUE} overlapping areas are intersected rather than replaced} } \value{ SpatRaster } \examples{ r1 <- r2 <- rast(ncols=36, nrows=18) values(r1) <- 1:ncell(r1) values(r2) <- runif(ncell(r2)) r2 <- classify(r2, cbind(-Inf, 0.5, NA)) r3 <- cover(r2, r1) p <- vect(system.file("ex/lux.shp", package="terra")) e <- as.polygons(ext(6, 6.4, 49.75, 50)) values(e) <- data.frame(y=10) cv <- cover(p, e) plot(cv, col=rainbow(12)) ci <- cover(p, e, identity=TRUE) lines(e, lwd=3) plot(ci, col=rainbow(12)) lines(e, lwd=3) } \keyword{methods} \keyword{spatial} terra/man/density.Rd0000644000175000017500000000144314201035750014241 0ustar nileshnilesh\name{density} \alias{density} \alias{density,SpatRaster-method} \docType{methods} \title{Density plot} \description{ Create density plots of the cell values of a SpatRaster } \usage{ \S4method{density}{SpatRaster}(x, maxcells=100000, plot=TRUE, main, ...) } \arguments{ \item{x}{SpatRaster} \item{maxcells}{the maximum number of (randomly sampled) cells to be used for creating the plot} \item{plot}{if \code{TRUE} produce a plot, else return a density object} \item{main}{character. Caption of plot(s)} \item{...}{additional arguments passed to \code{\link{plot}}} } \value{ density plot (and a density object, returned invisibly if \code{plot=TRUE)} } \examples{ logo <- rast(system.file("ex/logo.tif", package="terra")) density(logo) } \keyword{spatial} terra/man/crs.Rd0000644000175000017500000000600514201035750013350 0ustar nileshnilesh\name{crs} \docType{methods} \alias{crs} \alias{crs<-} \alias{crs,SpatRaster-method} \alias{crs,SpatRasterDataset-method} \alias{crs<-,SpatRaster-method} \alias{crs<-,SpatRaster,ANY-method} \alias{crs,SpatVector-method} \alias{crs,SpatVectorProxy-method} \alias{crs<-,SpatVector-method} \alias{crs<-,SpatVector,ANY-method} \title{ Get or set a coordinate reference system } \description{ Get or set the coordinate reference system (CRS), also referred to as a "projection", of a SpatRaster or SpatVector object. Setting a new CRS does not change the data itself, it just changes the label. So you should only set the CRS of a dataset (if it does not come with one) to what it *is*, not to what you would *like it to be*. See \code{\link{project}} to *transform* an object from one CRS to another. } \usage{ \S4method{crs}{SpatRaster}(x, proj=FALSE, describe=FALSE, parse=FALSE) \S4method{crs}{SpatVector}(x, proj=FALSE, describe=FALSE, parse=FALSE) \S4method{crs}{SpatRaster}(x)<-value \S4method{crs}{SpatVector}(x)<-value } \arguments{ \item{x}{SpatRaster or SpatVector} \item{proj}{logical. If \code{TRUE} the crs is returned in PROJ-string notation} \item{describe}{logical. If \code{TRUE} the name, EPSG code, and the name and extent of the area of use are returned if known} \item{value}{character string describing a coordinate reference system. This can be in a WKT format, as a code such as "EPSG:4326", or a PROJ-string format such as "+proj=utm +zone=12" (see Note)} \item{parse}{logical. If \code{TRUE}, wkt parts are parsed into a vector (each line becomes an element)} } \note{ Projections are handled by the PROJ/GDAL libaries. Recent changes in the PROJ library to improve transformations between datums have degraded the library's usability. The PROJ developers suggest to no longer use the proj-string notation to define a CRS, but use the WKT2 or : notation instead. These alternative systems work for formally described CRSs that are in databases, but they do not cover the infinite number of CRSs that exist. It is not practical to define one's own custom CRS with WKT2. Moreover, unlike the proj-notation, these newer systems are hard to read and that leads to code that cannot be easily understood and, therefore, is more error-prone. It is still possible to use the PROJ-string notation with one major caveat: the datum should be WGS84 (or the equivalent NAD83) -- if you want to transform your data to a coordinate reference system with a different datum. Thus as long as you use WGS84, or an ellipsoid instead of a datum, you can safely use PROJ-strings to represent your CRS; including to define your own custom CRS. } \value{ character or modified SpatRaster/Vector } \examples{ r <- rast() crs(r) crs(r, describe=TRUE, proj=TRUE) crs(r) <- "+proj=lcc +lat_1=48 +lat_2=33 +lon_0=-100 +ellps=WGS84" crs(r) # You can also use epsg codes crs(r) <- "epsg:25831" crs(r, describe=TRUE)$area } \keyword{ spatial } terra/man/window.Rd0000644000175000017500000000233314201035750014070 0ustar nileshnilesh\name{window} \docType{methods} \alias{window} \alias{window<-} \alias{window,SpatRaster-method} \alias{window<-,SpatRaster-method} \title{Set a window} \description{ \bold{Experimental}: Assign a window (area of interest) to a SpatRaster with a \code{SpatExtent}, or set it to \code{NULL} to remove the window. This is similar to \code{\link{crop}} without actually creating a new dataset. Currently, the window will be forced to intersect with the extent of the SpatRaster. It is envisioned that in future versions, the window may also go outside these boundaries. } \usage{ \S4method{window}{SpatRaster}(x)<-value \S4method{window}{SpatRaster}(x) } \arguments{ \item{x}{SpatRaster} \item{value}{SpatExtent} } \seealso{ \code{\link{crop}}, \code{\link{extend}} } \value{ none for \code{window<-} and logical for \code{window} } \examples{ f <- system.file("ex/elev.tif", package="terra") r <- rast(f) global(r, "mean", na.rm=TRUE) e <- ext(c(5.9, 6,49.95, 50)) window(r) <- e global(r, "mean", na.rm=TRUE) r x <- rast(f) xe <- crop(x, e) global(xe, "mean", na.rm=TRUE) b <- c(xe, r) window(b) b window(r) <- NULL r } \keyword{methods} \keyword{spatial} terra/man/app.Rd0000644000175000017500000000766114201035747013360 0ustar nileshnilesh\name{app} \docType{methods} \alias{app} \alias{app,SpatRaster-method} \alias{app,SpatRasterDataset-method} \title{Apply a function to the cells of a SpatRaster} \description{ Apply a function to the values of each cell of a SpatRaster. Similar to \code{\link[base]{apply}} -- think of each layer in a SpatRaster as a column (or row) in a matrix. This is generally used to summarize the values of multiple layers into one layer; but this is not required. \code{app} calls function \code{fun} with the raster data as first argument. Depending on the function supplied, the raster data is represented as either a matrix in which each layer is a column, or a vector representing a cell. The function should return a vector or matrix that is divisible by ncell(x). Thus, both "sum" and "rowSums" can be used, but "colSums" cannot be used. You can also apply a function \code{fun} across datasets by layer of a \code{SpatRasterDataset}. In that case, summarization is across SpatRasters, not across layers. } \usage{ \S4method{app}{SpatRaster}(x, fun, ..., cores=1, filename="", overwrite=FALSE, wopt=list()) \S4method{app}{SpatRasterDataset}(x, fun, ..., cores=1, filename="", overwrite=FALSE, wopt=list()) } \arguments{ \item{x}{SpatRaster or SpatRasterDataset} \item{fun}{a function that operates on a vector or matrix. This can be a function that is defined in base-R or in a package, or a function you write yourself (see examples). Functions that return complex output (e.g. a list) may need to be wrapped in your own function to simplify the output to a vector or matrix. The following functions have been re-implemented in C++ for speed: "sum", "mean", "median", "modal", "which", "which.min", "which.max", "min", "max", "prod", "any", "all", "sd", "std", "first". To use the base-R function for say, "min", you could use something like \code{fun=function(i) min(i)} or the equivalent \code{fun = \(i) min(i)}} \item{...}{additional arguments for \code{fun}. These are typically numerical constants. They should *never* be another SpatRaster} \item{cores}{positive integer. If \code{cores > 1}, a 'parallel' package cluster with that many cores is created and used. You can also supply a cluster object. Ignored for functions that are implemented by terra in C++ (see under fun)} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{list with named options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \details{ To speed things up, parallelization is supported, but this is often not helpful, and it may actually be slower. There is only a speed gain if you have many cores (> 8) and/or a very complex (slow) function \code{fun}. If you write \code{fun} yourself, consider supplying a \code{cppFunction} made with the Rcpp package instead (or go have a cup of tea while the computer works for you). } \seealso{ \code{\link{lapp}}, \code{\link{tapp}}, \code{\link[terra]{Math-methods}} } \examples{ r <- rast(ncols=10, nrows=10) values(r) <- 1:ncell(r) x <- c(r, sqrt(r), r+50) s <- app(x, fun=sum) s # for a few generic functions like # "sum", "mean", and "max" you can also do sum(x) ## SpatRasterDataset sd <- sds(x, x*2, x/3) a <- app(sd, max) a # same as max(x, x*2, x/3) ## also works for a single layer f <- function(i) (i+1) * 2 * i + sqrt(i) s <- app(r, f) # same as above, but that is not memory-safe # and has no filename argument s <- f(r) \dontrun{ #### multiple cores test0 <- app(x, sqrt) test1 <- app(x, sqrt, cores=2) testfun <- function(i) { 2 * sqrt(i) } test2 <- app(x, fun=testfun, cores =2) ## this fails because testfun is not exported to the nodes # test3 <- app(x, fun=function(i) testfun(i), cores=2) ## to export it, add it as argument to fun test3 <- app(x, fun=function(i, ff) ff(i), cores =3, ff=testfun) } } \keyword{methods} \keyword{spatial} terra/man/focalMat.Rd0000644000175000017500000000217114201035750014307 0ustar nileshnilesh\name{focalMat} \alias{focalMat} \title{Focal weights matrix} \description{ Make a focal ("moving window") weight matrix for use in the \code{\link{focal}} function. The sum of the values adds up to one. } \usage{ focalMat(x, d, type=c('circle', 'Gauss', 'rectangle'), fillNA=FALSE) } \arguments{ \item{x}{SpatRaster} \item{d}{numeric. If \code{type=circle}, the radius of the circle (in units of the crs). If \code{type=rectangle} the dimension of the rectangle (one or two numbers). If \code{type=Gauss} the size of sigma, and optionally another number to determine the size of the matrix returned (default is 3*sigma)} \item{type}{character indicating the type of filter to be returned} \item{fillNA}{logical. If \code{TRUE}, zeros are set to \code{NA} such that they are ignored in the computations. Only applies to \code{type="circle"}} } \value{ matrix that can be used with \code{\link{focal}} } \examples{ r <- rast(ncols=180, nrows=180, xmin=0) focalMat(r, 2, "circle") focalMat(r, c(2,3), "rect") # Gaussian filter for square cells gf <- focalMat(r, 1, "Gauss") } \keyword{spatial} terra/man/src.Rd0000644000175000017500000000213114201035750013344 0ustar nileshnilesh\name{sprc} \docType{methods} \alias{src} \alias{src,ANY-method} \alias{sprc} \alias{sprc,missing-method} \alias{sprc,list-method} \alias{sprc,SpatRaster-method} \title{Create a SpatRasterCollection} \description{ Methods to create a SpatRasterCollection. This is an object to hold a collection (list) of SpatRaster objects. There are no restrictions on the similarity of the SpatRaster geometry. They can be used to combine several SpatRasters to be used with \code{\link{merge}} or \code{\link{mosaic}} } \usage{ \S4method{sprc}{SpatRaster}(x, ...) \S4method{sprc}{list}(x) \S4method{sprc}{missing}(x) } \arguments{ \item{x}{SpatRaster, list with SpatRaster objects, or missing} \item{...}{additional SpatRaster objects} } \value{ SpatRasterCollection } \seealso{ \code{\link{sds}} } \examples{ x <- rast(xmin=-110, xmax=-50, ymin=40, ymax=70, ncols=60, nrows=30) y <- rast(xmin=-80, xmax=-20, ymax=60, ymin=30) res(y) <- res(x) values(x) <- 1:ncell(x) values(y) <- 1:ncell(y) z <- sprc(x, y) z } \keyword{methods} \keyword{spatial} terra/man/catalyze.Rd0000644000175000017500000000253514201035750014401 0ustar nileshnilesh\name{catalyze} \docType{methods} \alias{as.numeric} \alias{as.numeric,SpatRaster-method} \alias{catalyze} \alias{catalyze,SpatRaster-method} \title{Factors to numeric} \description{ Change a categorical layer into one or more numerical layers. With \code{as.numeric} you can transfer the active category values to cell values in a non categorical SpatRaster. \code{catalyze} transfers all categories to new layers. } \usage{ \S4method{as.numeric}{SpatRaster}(x, index=NULL, filename="", ...) \S4method{catalyze}{SpatRaster}(x, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{index}{positive integer, indicating the column in \code{data.frame} \code{value} to be used as the category, skipping the first column with the ID. If \code{NULL} the active category is used} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{\code{\link{activeCat}}, \code{\link{cats}}} \examples{ set.seed(0) r <- rast(nrows=10, ncols=10) values(r) <- sample(3, ncell(r), replace=TRUE) + 10 d <- data.frame(id=11:13, cover=c("forest", "water", "urban"), letters=letters[1:3], value=10:12) levels(r) <- d catalyze(r) activeCat(r) <- 3 as.numeric(r) } \keyword{methods} \keyword{spatial} terra/man/spin.Rd0000644000175000017500000000161414201035750013533 0ustar nileshnilesh\name{spin} \docType{methods} \alias{spin} \alias{spin,SpatVector-method} \title{spin a SpatVector} \description{ Spin (rotate) the geometry of a SpatVector. } \usage{ \S4method{spin}{SpatVector}(x, angle, x0, y0) } \arguments{ \item{x}{SpatVector} \item{angle}{numeric. Angle of rotation in degrees} \item{x0}{numeric. x-coordinate of the center of rotation. If missing, the center of the extent of \code{x} is used} \item{y0}{numeric. y-coordinate of the center of rotation. If missing, the center of the extent of \code{x} is used} } \value{ SpatVector } \seealso{\code{\link{rescale}}, \code{\link{t}}, \code{\link{shift}}} \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) w <- spin(v, 180) plot(v) lines(w, col="red") # lower-right corner as center e <- as.vector(ext(v)) x <- spin(v, 45, e[1], e[3]) } \keyword{spatial} terra/man/as.spatvector.Rd0000644000175000017500000000511514201035747015364 0ustar nileshnilesh\name{as.spatvector} \docType{methods} \alias{as.polygons} \alias{as.lines} \alias{as.points} \alias{as.polygons,SpatRaster-method} \alias{as.lines,SpatRaster-method} \alias{as.points,SpatRaster-method} \alias{as.polygons,SpatVector-method} \alias{as.lines,SpatVector-method} \alias{as.points,SpatVector-method} \alias{as.polygons,SpatExtent-method} \alias{as.lines,SpatExtent-method} \alias{as.points,SpatExtent-method} \title{Conversion to a SpatVector, or to another SpatVector type} \description{ Conversion of a SpatRaster or SpatExtent to a SpatVector of points, lines, or polygons; And conversion of a SpatVector to a another SpatVector type. } \usage{ \S4method{as.polygons}{SpatRaster}(x, trunc=TRUE, dissolve=TRUE, values=TRUE, na.rm=TRUE, extent=FALSE) \S4method{as.lines}{SpatRaster}(x) \S4method{as.points}{SpatRaster}(x, values=TRUE, na.rm=TRUE) \S4method{as.polygons}{SpatVector}(x) \S4method{as.lines}{SpatVector}(x) \S4method{as.points}{SpatVector}(x, multi=FALSE, skiplast=TRUE) \S4method{as.polygons}{SpatExtent}(x, crs="") \S4method{as.lines}{SpatExtent}(x, crs="") \S4method{as.points}{SpatExtent}(x, crs="") } \arguments{ \item{x}{SpatRaster or SpatVector} \item{trunc}{logical; truncate values to integers. Cels with the same value are merged. Therefore, if \code{trunc=FALSE} the object returned can be very large} \item{dissolve}{logical; combine cells with the same values? If \code{TRUE} only the first layer in \code{x} is processed} \item{values}{logical; include cell values as attributes? If \code{FALSE} the cells are not dissolved and the object returned can be very large} \item{multi}{logical. If \code{TRUE} a multipoint geometry is returned} \item{skiplast}{logical. If \code{TRUE} the last point of a polygon (which is the same as the first point) is not included} \item{extent}{logical. if \code{TRUE}, a polygon for the extent of the SpatRaster is returned. It has vertices for each grid cell, not just the four corners of the raster. This can be useful for more precise projection. In other cases it is better to do \code{as.polygons(ext(x))} to get a much smaller object returned that covers the same extent} \item{na.rm}{logical. If \code{TRUE} cells that are \code{NA} are ignored} \item{crs}{character. The coordinate reference system (see \code{\link{crs}}} } \value{ SpatVector } \examples{ r <- rast(ncols=2, nrows=2) values(r) <- 1:ncell(r) as.points(r) as.lines(ext(r), crs=crs(r)) if (gdal() >= "3.0.0") { p <- as.polygons(r) p as.lines(p) as.points(p) } } \keyword{spatial} terra/man/svc.Rd0000644000175000017500000000202114201035750013346 0ustar nileshnilesh\name{svc} \docType{methods} \alias{svc} \alias{svc,missing-method} \alias{svc,list-method} \alias{svc,SpatVector-method} \alias{[<-,SpatVectorCollection,numeric,missing-method} \alias{[,SpatVectorCollection,numeric,missing-method} \alias{[[,SpatVectorCollection,numeric,missing-method} \title{Create a SpatVectorCollection} \description{ Methods to create a SpatVectorCollection. This is an object to hold "sub-datasets", each a SpatVector, perhaps of different geometry type. } \usage{ \S4method{svc}{missing}(x) \S4method{svc}{SpatVector}(x, ...) \S4method{svc}{list}(x) } \arguments{ \item{x}{SpatVector, or list of a SpatVector, or missing} \item{...}{Additional \code{SpatVector}s} } \value{ SpatVectorCollection } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) x <- svc() x <- svc(v, v[1:3,], as.lines(v[3:5,]), as.points(v)) length(x) x # extract x[3] # replace x[2] <- as.lines(v[1,]) } \keyword{methods} \keyword{spatial} terra/man/cartogram.Rd0000644000175000017500000000156214201035750014543 0ustar nileshnilesh\name{cartogram} \docType{methods} \alias{cartogram} \alias{cartogram,SpatVector-method} \title{Cartogram} \description{ Make a cartogram, that is, a map where the area of polygons is made proportional to another variable. This can be a good way to map raw count data (e.g. votes). } \usage{ \S4method{cartogram}{SpatVector}(x, var, type) } \arguments{ \item{x}{SpatVector} \item{var}{character. A variable name in \code{x}} \item{type}{character. Cartogram type, only "nc" (non-contiguous) is currently supported} } \value{ SpatVector } \seealso{ \code{\link{plot}}, \code{\link{rescale}} } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) v$value <- 1:12 p <- cartogram(v, "value", "nc") plot(v, col="light gray", border="gray") lines(p, col="red", lwd=2) } \keyword{methods} \keyword{spatial} terra/man/wrap.Rd0000644000175000017500000000151014201035750013526 0ustar nileshnilesh\name{wrap} \alias{wrap} \alias{wrap,SpatVector-method} \alias{wrap,SpatRaster-method} \alias{wrap,Spatial-method} \title{wrap (pack) a SpatRaster or SpatVector object} \description{ Wrap a SpatRaster or SpatVector object to create a Packed* object. Packed objects can be saved as an R object to disk (.rds or .RData), or passed over a connection that serializes (e.g. to nodes on a computer cluster); but with large datasets passing a filename could be more sensible in that context. } \usage{ \S4method{wrap}{SpatRaster}(x) \S4method{wrap}{SpatVector}(x) } \arguments{ \item{x}{SpatVector or SpatRaster} } \value{ Packed* object } \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) p <- wrap(v) p vv <- vect(p) vv } \keyword{ spatial } \keyword{ methods } terra/man/rotate.Rd0000644000175000017500000000172014201035750014056 0ustar nileshnilesh\name{rotate} \docType{methods} \alias{rotate} \alias{rotate,SpatRaster-method} \title{Rotate a SpatRaster along longitude} \description{ Rotate a SpatRaster that has longitude coordinates from 0 to 360, to standard coordinates between -180 and 180 degrees (or vice-versa). Longitude between 0 and 360 is frequently used in global climate models. } \usage{ \S4method{rotate}{SpatRaster}(x, left=TRUE, filename="", ...) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{left}{logical. If \code{TRUE}, rotate to the left, else to the right} \item{filename}{character. Output filename} \item{...}{additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{\code{\link{shift}} and \code{\link{spin}}} \examples{ x <- rast(nrows=9, ncols=18, nl=3, xmin=0, xmax=360) v <- rep(as.vector(t(matrix(1:ncell(x), nrow=9, ncol=18))), 3) values(x) <- v z <- rotate(x) } \keyword{spatial} terra/man/ext.Rd0000644000175000017500000000345114201035750013363 0ustar nileshnilesh\name{ext} \docType{methods} \alias{$,SpatExtent-method} \alias{$<-,SpatExtent-method} \alias{[,SpatExtent,missing,missing-method} \alias{[,SpatExtent,numeric,missing-method} \alias{[<-,SpatExtent,numeric,missing-method} \alias{ext} \alias{ext<-} \alias{ext,SpatExtent-method} \alias{ext,SpatRaster-method} \alias{ext,SpatVector-method} \alias{ext,SpatVectorProxy-method} \alias{ext,SpatRasterDataset-method} \alias{ext<-,SpatRaster,SpatExtent-method} \alias{ext<-,SpatRaster,numeric-method} \alias{ext,numeric-method} \alias{ext,missing-method} \alias{ext,Spatial-method} \alias{ext,Raster-method} \alias{ext,Extent-method} \alias{ext,sf-method} \title{Create, get or set a SpatExtent} \description{ Get a SpatExtent of a SpatRaster, or coordinates from such an object. Or create a SpatExtent from a vector (length=4; order= xmin, xmax, ymin, ymax) See \code{\link{set.ext}} to set the extent in place. } \usage{ \S4method{ext}{SpatRaster}(x) \S4method{ext}{SpatVector}(x) \S4method{ext}{numeric}(x, ...) \S4method{ext}{SpatRaster,SpatExtent}(x)<-value \S4method{ext}{SpatRaster,numeric}(x)<-value \S4method{$}{SpatExtent}(x, name) \S4method{$}{SpatExtent}(x, name)<-value } \arguments{ \item{x}{SpatRaster} \item{value}{SpatExtent, or numeric vector of lenght four (xmin, xmax, ymin, ymax), or a single number with the \code{$} method} \item{name}{charcter, one of xmin, xmax, ymin, or ymax} \item{...}{if \code{x} is a single numeric value, additional numeric values for xmax, ymin, and ymax} } \value{ SpatExtent } \examples{ r <- rast() e <- ext(r) as.vector(e) as.character(e) ext(r) <- c(0, 2.5, 0, 1.5) r er <- ext(r) round(er) # go "in" floor(er) # go "out" ceiling(er) ext(r) <- e } \keyword{spatial} terra/man/mergeTime.Rd0000644000175000017500000000232214201035750014475 0ustar nileshnilesh\name{mergeTime} \docType{methods} \alias{mergeTime} \alias{mergeTime,SpatRasterDataset-method} \title{ merge SpatRasters by timelines to create a single timeseries } \description{ Combine SpatRasters with partly overlapping time-stamps to create a single time series. If there is no overlap between the SpatRasters there is no point in using this function (use \code{\link{c}} instead). Also note that time gaps are not filled. You can use \code{\link{fillTime}} to do that. } \usage{ \S4method{mergeTime}{SpatRasterDataset}(x, fun=mean, filename="", ...) } \arguments{ \item{x}{SpatRasterDataset} \item{fun}{A function that reduces a vector to a single number, such as \code{mean} or \code{min}} \item{filename}{character. Output filename} \item{...}{list with named options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \examples{ r <- rast(system.file("ex/logo.tif", package="terra")) s1 <- c(r, r) time(s1) <- as.Date("2001-01-01") + 0:5 s1 <- s1/10 time(s1) <- as.Date("2001-01-07") + 0:5 s2 <- s1*10 time(s2) <- as.Date("2001-01-05") + 0:5 x <- sds(s1, s1, s2) m <- mergeTime(x, mean) } \keyword{methods} \keyword{spatial} terra/man/SpatExtent-class.Rd0000644000175000017500000000137314201035747015774 0ustar nileshnilesh\name{SpatExtent-class} \docType{class} \alias{SpatExtent} \alias{SpatExtent-class} \alias{Rcpp_SpatExtent-class} \alias{show,SpatExtent-method} \title{Class "SpatExtent" } \description{ Objects of class SpatExtent are used to define the spatial extent (extremes) of objects of the SpatRaster class. } \section{Objects from the Class}{ You can use the \code{\link{ext}} function to create SpatExtent objects, or to extract them from SpatRaster objects. } \section{Slots}{ \describe{ \item{\code{ptr}:}{pointer to the C++ class} } } \section{Methods}{ \describe{ \item{show}{display values of a SpatExtent object } } } \examples{ e <- ext(-180, 180, -90, 90) e } \keyword{classes} \keyword{spatial} terra/man/SpatRaster-class.Rd0000644000175000017500000000203614201035747015762 0ustar nileshnilesh\name{SpatRaster-class} \docType{class} \alias{SpatRaster} \alias{SpatRaster-class} \alias{Rcpp_SpatRaster-class} \alias{PackedSpatRaster-class} \alias{RasterSource} \alias{RasterSource-class} \alias{Rcpp_RasterSource-class} \alias{SpatCategories} \alias{SpatCategories-class} \alias{Rcpp_SpatCategories-class} \alias{show,SpatRaster-method} \title{ SpatRaster class} \description{ A SpatRaster represents a rectangular part of the world that is sub-divided into rectangular cells of equal area (in terms of the units of the coordinate reference system). For each cell can have multiple values ("layers"). An object of the \code{SpatRaster} class can point to one or more files on disk that hold the cell values, and/or it can hold these values in memory. These objects can be created with the \code{\link{rast}} method. The underlying C++ class "Rcpp_SpatRaster" is not intended for end-users. It is for internal use within this package only. } \examples{ rast() } \keyword{classes} \keyword{spatial} terra/man/is.lonlat.Rd0000644000175000017500000000274714201035750014475 0ustar nileshnilesh\name{is.lonlat} \alias{is.lonlat} \alias{is.lonlat,SpatRaster-method} \alias{is.lonlat,SpatVector-method} \title{Check for longitude/latitude crs} \description{ Test whether a SpatRaster or SpatVector has a longitude/latitude coordinate reference system (CRS), or perhaps has one. That is wen the CRS is unknown (\code{""}) but the x coordinates are within -181 and 181 and the y coordinates are within -90.1 and 90.1. For a SpatRaster you can also test if it is longitude/latitude and "global" (covers all longitudes). } \usage{ \S4method{is.lonlat}{SpatRaster}(x, perhaps=FALSE, warn=TRUE, global=FALSE) \S4method{is.lonlat}{SpatVector}(x, perhaps=FALSE, warn=TRUE) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{perhaps}{logical. If \code{TRUE} and the crs is unknown, the method returns \code{TRUE} if the coordinates are plausible for longitude/latitude} \item{warn}{logical. If \code{TRUE}, a warning is given if the CRS is unknown or when the CRS is longitude/latitude but the coordinates do not match that} \item{global}{logical. If \code{TRUE}, the method tests if the raster covers all longitudes (from -180 to 180 degrees) such that the extreme columns are in fact adjacent } } \value{ logical or NA } \examples{ r <- rast() is.lonlat(r) is.lonlat(r, global=TRUE) crs(r) <- "" is.lonlat(r) is.lonlat(r, perhaps=TRUE, warn=FALSE) crs(r) <- "+proj=lcc +lat_1=48 +lat_2=33 +lon_0=-100 +ellps=WGS84" is.lonlat(r) } \keyword{spatial} terra/man/compare-generics.Rd0000644000175000017500000000370214201035750016005 0ustar nileshnilesh\name{Compare-methods} \docType{methods} \alias{Compare-methods} \alias{Logic-methods} \alias{Compare,SpatRaster,SpatRaster-method} \alias{Compare,numeric,SpatRaster-method} \alias{Compare,SpatRaster,numeric-method} \alias{Compare,SpatRaster,character-method} \alias{Logic,SpatRaster,SpatRaster-method} \alias{Logic,SpatRaster,numeric-method} \alias{Logic,numeric,SpatRaster-method} \alias{Logic,SpatRaster,logical-method} \alias{Logic,logical,SpatRaster-method} \alias{Compare,SpatExtent,SpatExtent-method} \alias{is.na,SpatRaster-method} \alias{is.nan,SpatRaster-method} \alias{!,SpatRaster-method} \alias{is.finite,SpatRaster-method} \alias{is.infinite,SpatRaster-method} \title{Compare and logical methods} \description{ Standard comparison and logical operators for computations with SpatRasters. Computations are local (applied on a cell by cell basis). If multiple SpatRaster objects are used, these must have the same geometry (extent and resolution). These operators have been implemented: \bold{Logical}: \code{!, &, |, isTRUE, isFALSE} \bold{Compare}: \code{ ==, !=, >, <, <=, >=, is.na, is.nan, is.finite, is.infinite} The terra package does not distinguish between \code{NA} (not available) and \code{NaN} (not a number). In most cases this state is represented by \code{NaN}. The following method has been implemented for \bold{(SpatExtent, SpatExtent)}: \code{==} } \section{seealso}{ \code{\link{all.equal}}, \link{Arith-methods}. See \code{\link{ifel}} to conveniently combine operations and \code{\link{Math-methods}} or \code{\link{app}} to use mathematical functions not implemented by the package. } \value{ SpatRaster or SpatExtent } \examples{ r1 <- rast(ncols=10, nrows=10) v <- runif(ncell(r1)) v[10:20] <- NA values(r1) <- v r2 <- rast(r1) values(r2) <- 1:ncell(r2) / ncell(r2) x <- is.na(r1) !x r1 == r2 } \keyword{methods} \keyword{math} \keyword{spatial} terra/man/sds.Rd0000644000175000017500000000353014201035750013352 0ustar nileshnilesh\name{sds} \docType{methods} \alias{sds} \alias{sds,missing-method} \alias{sds,character-method} \alias{sds,list-method} \alias{sds,array-method} \alias{sds,SpatRaster-method} \alias{sds,stars-method} \alias{sds,stars_proxy-method} \alias{[<-,SpatRasterDataset,numeric,missing-method} \title{Create a SpatRasterDataset} \description{ Methods to create a SpatRasterDataset. This is an object to hold "sub-datasets", each a SpatRaster that in most cases will have multiple layers. See \code{\link{describe}} for getting information about the sub-datasets present in a file. } \usage{ \S4method{sds}{missing}(x) \S4method{sds}{character}(x, ids=0) \S4method{sds}{SpatRaster}(x, ...) \S4method{sds}{list}(x) \S4method{sds}{array}(x, crs="", extent=NULL) } \arguments{ \item{x}{character (filename), or SpatRaster, or list of SpatRaster objects, or missing. If multiple filenames are provided, it is attempted to make SpatRasters from these, and combine them into a SpatRasterDataset} \item{ids}{optional. vector of integer subdataset ids. Ignored if the first value is not a positive integer} \item{crs}{character. Description of the Coordinate Reference System (map projection) in \code{PROJ.4}, \code{WKT} or \code{authority:code} notation. If this argument is missing, and the x coordinates are within -360 .. 360 and the y coordinates are within -90 .. 90, longitude/latitude is assigned} \item{extent}{\code{\link{SpatExtent}}} \item{...}{additional \code{SpatRaster} objects} } \value{ SpatRasterDataset } \seealso{ \code{\link{describe}} } \examples{ s <- rast(system.file("ex/logo.tif", package="terra")) x <- sds(s, s/2) names(x) <- c("first", "second") x length(x) # extract the second SpatRaster x[2] a <- array(1:9, c(3,3,3,3)) sds(a) } \keyword{methods} \keyword{spatial} terra/man/inset.Rd0000644000175000017500000000624214201035750013706 0ustar nileshnilesh\name{inset} \docType{methods} \alias{inset} \alias{inset,SpatVector-method} \alias{inset,SpatRaster-method} \alias{inext} \alias{inext,SpatVector-method} \title{Make an inset map} \description{ Make an inset map or scale the extent of a SpatVector } \usage{ \S4method{inset}{SpatVector}(x, e, loc="", scale=0.2, background="white", perimeter=TRUE, box=NULL, pper, pbox, ...) \S4method{inset}{SpatRaster}(x, e, loc="", scale=0.2, background="white", perimeter=TRUE, box=NULL, pper, pbox, ...) \S4method{inext}{SpatVector}(x, e, y=NULL, gap=0) } \arguments{ \item{x}{SpatVector, SpatRaster} \item{e}{SpatExtent to set the size and location of the inset. Or missing} \item{loc}{character. One of "bottomright", "bottom", "bottomleft", "left", "topleft", "top", "topright", "right", "center"} \item{scale}{numeric. The relative size of the inset, used when x is missing} \item{background}{color for the background of the inset. Use \code{NA} for no background color} \item{perimeter}{logical. If \code{TRUE} a perimeter (border) is drawn around the inset} \item{box}{SpatExtent or missing, to draw a box on the inset, e.g. to show where the map is located in a larger area} \item{pper}{list with graphical parameters (arguments) such as \code{col} and \code{lwd} for the perimeter line} \item{pbox}{list with graphical parameters (arguments) such as \code{col} and \code{lwd} for the box (line)} \item{...}{additional arguments passed to plot for the drawing of \code{x}} \item{y}{SpatVector. If not NULL, \code{y} is scaled based with the parameters for \code{x}. This is useful, for example, when \code{x} represent boundaries, and \code{y} points within these boundaries} \item{gap}{numeric to add space between the SpatVector and the SpatExtent} } \seealso{\code{\link{sbar}}, \code{\link{rescale}}, \code{\link{shift}}} \value{scaled and shifted SpatVector or SpatRaster (returned invisibly)} \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f) x <- v[v$NAME_2 == "Diekirch", ] plot(x, density=10, col="blue") inset(v) # more elaborate plot(x, density=10, col="blue") inset(v, col = "brown", border="lightgrey", perimeter=TRUE, pper=list(col="orange", lwd=3, lty=2), box=ext(x), pbox=list(col="blue", lwd=2)) cols <- rep("light grey", 12) cols[2] <- "red" e <- ext(c(6.2, 6.3, 49.9, 50)) b <- ext(x)+0.02 inset(v, e=e, col=cols, box=b) # with a SpatRaster ff <- system.file("ex/elev.tif", package="terra") r <- rast(ff) r <- crop(r, ext(x) + .01) plot(r, type="int", mar=c(2,2,2,2), plg=list(x="topright")) lines(v, lwd=1.5) lines(x, lwd=2.5) inset(v, col=cols, loc="topleft", scale=0.15) # a more complex one plot(r, plg=list(title="meter\n", shrink=.2, cex=.8)) lines(v, lwd=4, col="white") lines(v, lwd=1.5) lines(x, lwd=2.5) text(x, "NAME_2", cex=1.5, halo=TRUE) sbar(6, c(6.04, 49.785), type="bar", below="km", label=c(0,3,6), cex=.8) s <- inset(v, col=cols, box=b, scale=.2, loc="topright", background="light yellow", pbox=list(lwd=2, lty=5, col="blue")) # note the returned inset SpatVector s lines(s, col="orange") } \keyword{methods} \keyword{spatial} terra/man/selectHigh.Rd0000644000175000017500000000146114201035750014641 0ustar nileshnilesh\name{selectHighest} \docType{methods} \alias{selectHighest} \alias{selectHighest,SpatRaster-method} \title{select cells with high or low values} \description{ Identify n cells that have the highest of lowest values in the first layer of a SpatRaster. } \usage{ \S4method{selectHighest}{SpatRaster}(x, n, low=FALSE) } \arguments{ \item{x}{SpatRaster. Only the first layer is processed} \item{n}{The number of cells to select} \item{low}{logical. If \code{TRUE}, the lowest values are selected instead of the highest values} } \value{ SpatRaster } \examples{ f <- system.file("ex/elev.tif", package="terra") r <- rast(f) x <- selectHighest(r, 1000) y <- selectHighest(r, 1000, TRUE) m <- merge(y-1, x) levels(m) <- c("low", "high") plot(m) } \keyword{spatial} terra/man/query.Rd0000644000175000017500000000276214201035750013734 0ustar nileshnilesh\name{query} \docType{methods} \alias{query} \alias{query,SpatVectorProxy-method} \title{Query a SpatVectorProxy object} \description{ Query a SpatVectorProxy to extract a subset } \usage{ \S4method{query}{SpatVectorProxy}(x, start=1, n=nrow(x), vars=NULL, where=NULL, extent=NULL, filter=NULL) } \arguments{ \item{x}{SpatVectorProxy} \item{start}{positive integer. The record to start reading at} \item{n}{positive integer. The number of records requested} \item{vars}{character. Variable names. Must be a subset of \code{names(x)}} \item{where}{character. expression like "NAME_1='California' AND ID > 3" , to subset records. Note that start and n are applied after executing the where statement} \item{extent}{Spat* object. The extent of the object is used as a spatial filter to select the geometries to read. Ignored if \code{filter} is not \code{NULL}} \item{filter}{SpatVector. Used as a spatial filter to select geometries to read (the convex hull is used for lines or points)} } \seealso{\code{\link{vect}}} \value{SpatVector} \examples{ f <- system.file("ex/lux.shp", package="terra") v <- vect(f, proxy=TRUE) v x <- query(v, vars=c("ID_2", "NAME_2"), start=5, n=2) x query(v, vars=c("ID_2", "NAME_1", "NAME_2"), where="NAME_1='Grevenmacher' AND ID_2 > 6") ## with an extent e <- ext(5.9, 6.3, 49.9, 50) x <- query(v, extent=e) ## with polygons p <- as.polygons(e) x <- query(v, filter=p) x } \keyword{methods} \keyword{spatial} terra/man/collapse.Rd0000644000175000017500000000125014201035750014360 0ustar nileshnilesh\name{tighten} \docType{methods} \alias{tighten} \alias{tighten,SpatRaster-method} \alias{tighten,SpatRasterDataset-method} \title{tighten SpatRaster or SpatRasterDataset objects} \description{ Combines data sources within a SpatRaster object (that are in memory, or from the same file) to allow for faster processing. Or combine sub-datsets into a SpatRaster. } \usage{ \S4method{tighten}{SpatRaster}(x) \S4method{tighten}{SpatRasterDataset}(x) } \arguments{ \item{x}{SpatRaster or SpatRasterDataset} } \value{ SpatRaster } \examples{ r <- rast(nrow=5, ncol=9, vals=1:45) x <- c(r, r*2, r*3) x tighten(x) } \keyword{spatial} terra/man/patches.Rd0000644000175000017500000000464514201035750014220 0ustar nileshnilesh\name{patches} \alias{patches} \alias{patches,SpatRaster-method} \title{Detect patches (clumps) of cells} \description{ Detect patches (clumps). Patches are groups of cells that are surrounded by cells that are \code{NA}. Set \code{zeroAsNA} to \code{TRUE} to also identify patches separated by cells with values of zero. } \usage{ \S4method{patches}{SpatRaster}(x, directions=4, zeroAsNA=FALSE, allowGaps=TRUE, filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{directions}{integer indicating which cells are considered adjacent. Should be 8 (Queen's case) or 4 (Rook's case)} \item{zeroAsNA}{logical. If \code{TRUE} treat cells that are zero as if they were \code{NA}} \item{allowGaps}{logical. If \code{TRUE} there may be gaps in the patch IDs (e.g. you may have patch IDs 1, 2, 3 and 5, but not 4). If it is FALSE, these numbers will be recoded from 1 to the number of patches (4 in this example)} \item{filename}{character. Output filename} \item{...}{options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster. Cell values are patch numbers } \seealso{ \code{\link{focal}}, \code{\link{boundaries}} } \examples{ r <- rast(nrows=18, ncols=36, xmin=0) r[1:2, 5:8] <- 1 r[5:8, 2:6] <- 1 r[7:12, 22:36] <- 1 r[15:16, 18:29] <- 1 p <- patches(r) # zero as background instead of NA r <- rast(nrows=10, ncols=10, xmin=0, vals=0) r[3, 3] <- 10 r[4, 4] <- 10 r[5, 5:8] <- 12 r[6, 6:9] <- 12 # treat zeros as NA p4 <- patches(r, zeroAsNA=TRUE) p8 <- patches(r, 8, zeroAsNA=TRUE) ### patches for different values # remove zeros manually rr <- classify(r, cbind(0, NA)) # make layers for each value s <- segregate(rr, keep=TRUE, other=NA) p <- patches(s) ### patch ID values are not guaranteed to be consecutive r <- rast(nrows=5, ncols=10, xmin=0) set.seed(0) values(r)<- round(runif(ncell(r))*0.7) rp <- patches(r, directions=8, zeroAsNA=TRUE) plot(rp, type="classes"); text(rp) ## unless you set allowGaps=FALSE rp <- patches(r, directions=8, zeroAsNA=TRUE, allowGaps=FALSE) plot(rp, type="classes"); text(rp) ### use zonal to remove small patches f <- system.file("ex/elev.tif", package="terra") r <- rast(f) x <- classify(r, cbind(-Inf, 400, NA)) y <- patches(x) # remove patches smaller than 100 ha rz <- zonal(cellSize(y, unit="ha"), y, sum, as.raster=TRUE) s <- ifel(rz < 100, NA, y) } \keyword{methods} \keyword{spatial} terra/man/xmin.Rd0000644000175000017500000000363714201035750013544 0ustar nileshnilesh\name{xmin} \docType{methods} \alias{xmin} \alias{xmax} \alias{ymin} \alias{ymax} \alias{xmin<-} \alias{xmax<-} \alias{ymin<-} \alias{ymax<-} \alias{xmin,SpatExtent-method} \alias{xmin,SpatRaster-method} \alias{xmin,SpatVector-method} \alias{xmax,SpatExtent-method} \alias{xmax,SpatRaster-method} \alias{xmax,SpatVector-method} \alias{ymin,SpatExtent-method} \alias{ymin,SpatRaster-method} \alias{ymin,SpatVector-method} \alias{ymax,SpatExtent-method} \alias{ymax,SpatRaster-method} \alias{ymax,SpatVector-method} \alias{xmin<-,SpatExtent,numeric-method} \alias{xmin<-,SpatRaster,numeric-method} \alias{xmax<-,SpatExtent,numeric-method} \alias{xmax<-,SpatRaster,numeric-method} \alias{ymin<-,SpatExtent,numeric-method} \alias{ymin<-,SpatRaster,numeric-method} \alias{ymax<-,SpatExtent,numeric-method} \alias{ymax<-,SpatRaster,numeric-method} \title{Get or set single values of an extent} \description{ Get or set single values of an extent. Values can be set for a SpatExtent or SpatRaster, but not for a SpatVector) } \usage{ \S4method{xmin}{SpatExtent}(x) \S4method{xmax}{SpatExtent}(x) \S4method{ymin}{SpatExtent}(x) \S4method{ymax}{SpatExtent}(x) \S4method{xmin}{SpatRaster}(x) \S4method{xmax}{SpatRaster}(x) \S4method{ymin}{SpatRaster}(x) \S4method{ymax}{SpatRaster}(x) \S4method{xmin}{SpatVector}(x) \S4method{xmax}{SpatVector}(x) \S4method{ymin}{SpatVector}(x) \S4method{ymax}{SpatVector}(x) \S4method{xmin}{SpatRaster,numeric}(x)<-value \S4method{xmax}{SpatRaster,numeric}(x)<-value \S4method{ymin}{SpatRaster,numeric}(x)<-value \S4method{ymax}{SpatRaster,numeric}(x)<-value } \arguments{ \item{x}{SpatRaster, SpatExtent, or SpatVector} \item{value}{numeric} } \value{ SpatExtent or numeric coordinate } \examples{ r <- rast() ext(r) ext(c(0, 20, 0, 20)) xmin(r) xmin(r) <- 0 xmin(r) } \keyword{spatial} terra/man/global.Rd0000644000175000017500000000310614201035750014020 0ustar nileshnilesh\name{global} \alias{global} \alias{global,SpatRaster-method} \title{global statistics} \description{ Compute global statistics, that is summarized values of an entire SpatRaster. If \code{x} is very large \code{global} will fail, except when \code{fun} is one of "mean", "min", "max", "sum", "range" (min and max), "rms" (root mean square), "sd" (sample standard deviation), "sdpop" (population standard deviation), "isNA" (number of cells that are NA), "notNA" (number of cells that are not NA). You can compute a weighted mean or sum by providing a SpatRaster with weights. } \usage{ \S4method{global}{SpatRaster}(x, fun="mean", weights=NULL, ...) } \arguments{ \item{x}{SpatRaster} \item{fun}{function to be applied to summarize the values by zone. Either as one of these character values: "max", "min", "mean", "sum", "range", "rms" (root mean square), "sd", "std" (population sd, using \code{n} rather than \code{n-1}); or, for relatively small SpatRasters, a proper function} \item{...}{additional arguments passed on to \code{fun}} \item{weights}{NULL or SpatRaster} } \value{ A \code{data.frame} with a row for each layer } \seealso{\code{\link{zonal}} for "zonal" statistics, and \code{\link{app}} or \code{\link{Summary-methods}} for "local" statistics, and \code{\link{extract}} for summarizing values for polygons. Also see \code{\link{focal}} for "focal" or "moving window" operations.} \examples{ r <- rast(ncols=10, nrows=10) values(r) <- 1:ncell(r) global(r, "sum") global(r, "mean", na.rm=TRUE) } \keyword{spatial} terra/man/cells.Rd0000644000175000017500000000413514201035750013665 0ustar nileshnilesh\name{cells} \docType{methods} \alias{cells} \alias{cells,SpatRaster,missing-method} \alias{cells,SpatRaster,numeric-method} \alias{cells,SpatRaster,SpatVector-method} \alias{cells,SpatRaster,SpatExtent-method} \title{Get cell numbers} \description{ Get the cell numbers covered by a SpatVector or SpatExtent. Or that match values in a vector; or all non \code{NA} values. } \usage{ \S4method{cells}{SpatRaster,missing}(x, y) \S4method{cells}{SpatRaster,numeric}(x, y) \S4method{cells}{SpatRaster,SpatVector}(x, y, method="simple", weights=FALSE, exact=FALSE, touches=is.lines(y)) \S4method{cells}{SpatRaster,SpatExtent}(x, y) } \arguments{ \item{x}{SpatRaster} \item{y}{SpatVector, SpatExtent, 2-column matrix representing points, numeric representing values to match, or missing} \item{method}{character. Method for getting cell numbers for points. The default is "simple", the alternative is "bilinear". If it is "bilinear", the four nearest cells and their weights are returned} \item{weights}{logical. If \code{TRUE} and \code{y} has polygons, the approximate fraction of each cell that is covered is returned as well} \item{exact}{logical. If \code{TRUE} and \code{y} has polygons, the exact fraction of each cell that is covered is returned as well} \item{touches}{logical. If \code{TRUE}, values for all cells touched by lines or polygons are extracted, not just those on the line render path, or whose center point is within the polygon. Not relevant for points} } \value{ numeric vector or matrix } \examples{ r <- rast(ncols=10, nrows=10) values(r) <- 1:ncell(r) r[c(1:25, 31:100)] <- NA r <- ifel(r > 28, r + 10, r) # all cell numbers of cells that are not NA cells(r) # cell numbers that match values x <- cells(r, c(28,38)) x$lyr.1 # cells for points m <- cbind(x=c(0,10,-30), y=c(40,-10,20)) cellFromXY(r, m) v <- vect(m) cells(r, v) cells(r, v, method="bilinear") # cells for polygons f <- system.file("ex/lux.shp", package="terra") v <- vect(f) r <- rast(v) cv <- cells(r, v) } \keyword{methods} \keyword{spatial} terra/man/text.Rd0000644000175000017500000000243414201035750013547 0ustar nileshnilesh\name{text} \docType{methods} \alias{text} \alias{text,SpatRaster-method} \alias{text,SpatVector-method} \title{Add labels to a map} \description{ Plots labels, that is a textual (rather than color) representation of values, on top an existing plot (map). } \usage{ \S4method{text}{SpatRaster}(x, labels, digits=0, halo=FALSE, ...) \S4method{text}{SpatVector}(x, labels, halo=FALSE, ...) } \arguments{ \item{x}{SpatRaster or SpatVector} \item{labels}{character. Optional. Vector of labels with \code{length(x)} or a variable name from \code{names(x)}} \item{digits}{integer. how many digits should be used?} \item{halo}{logical. If \code{TRUE} a "halo" is printed around the text. If \code{TRUE}, additional arguments \code{hc="white"} and \code{hw=0.1} can be modified to set the colour and width of the halo} \item{...}{additional arguments to pass to graphics function \code{\link[graphics]{text}} } } \seealso{ \code{\link[graphics]{text}, \link{plot}} } \examples{ r <- rast(nrows=4, ncols=4) values(r) <- 1:ncell(r) plot(r) text(r) plot(r) text(r, halo=TRUE, hc="blue", col="white", hw=0.2) plot(r, col=rainbow(16)) text(r, col=c("black", "white"), vfont=c("sans serif", "bold"), cex=2) } \keyword{methods} \keyword{spatial} terra/man/layerCor.Rd0000644000175000017500000000437314201035750014347 0ustar nileshnilesh\name{layerCor} \alias{layerCor} \alias{layerCor,SpatRaster-method} \title{Correlation and (weighted) covariance} \description{ Compute correlation, (weighted) covariance, or similar summary statistics that compare the values of all pairs of the layers of a SpatRaster. } \usage{ \S4method{layerCor}{SpatRaster}(x, fun, w, asSample=TRUE, na.rm=FALSE, maxcell=Inf, ...) } \arguments{ \item{x}{SpatRaster} \item{fun}{character. The statistic to compute: either "cov" (covariance), "weighted.cov" (weighted covariance), or "pearson" (correlation coefficient) or your own function that takes two vectors as argument to comptue a single number} \item{w}{SpatRaster with the weights to compute the weighted covariance. It should have a single layer and the same geometry as \code{x}} \item{asSample}{logical. If \code{TRUE}, the statistic for a sample (denominator is \code{n-1}) is computed, rather than for the population (denominator is \code{n}). Only for the standard functions} \item{na.rm}{logical. Should missing values be removed?} \item{maxcell}{postive integer. The number of cells to be regularly sampled. Only used when \code{fun} is a function} \item{...}{additional arguments for \code{fun} (if it is a proper function)} } \value{ If \code{fun} is one of the three standard statistics, you get a list with two items: the correlation or (weighted) covariance matrix, and the (weighted) means. If \code{fun} is a function, you get a matrix. } \references{ For the weighted covariance: \itemize{ \item {Canty, M.J. and A.A. Nielsen, 2008. Automatic radiometric normalization of multitemporal satellite imagery with the iteratively re-weighted MAD transformation. Remote Sensing of Environment 112:1025-1036.} \item {Nielsen, A.A., 2007. The regularized iteratively reweighted MAD method for change detection in multi- and hyperspectral data. IEEE Transactions on Image Processing 16(2):463-478.} } } \seealso{ \code{\link{global}}, \code{\link{cov.wt}}, \code{\link{weighted.mean}} } \examples{ b <- rast(system.file("ex/logo.tif", package="terra")) layerCor(b, "pearson") layerCor(b, "cov") # weigh by column number w <- init(b, fun="col") layerCor(b, "weighted.cov", w=w) } terra/man/convhull.Rd0000644000175000017500000000161214201035750014412 0ustar nileshnilesh\name{convHull} \docType{methods} \alias{convHull} \alias{convHull,SpatVector-method} \alias{minRect} \alias{minRect,SpatVector-method} \title{ Convex hull and minimal rotated rectangle } \description{ Get the convex hull or the minimal rotated rectangle of a SpatVector } \usage{ \S4method{convHull}{SpatVector}(x, by="") \S4method{minRect}{SpatVector}(x, by="") } \arguments{ \item{x}{SpatVector} \item{by}{character (variable name), to make convex hulls by group} } \value{ SpatVector } \examples{ p <- vect(system.file("ex/lux.shp", package="terra")) h <- convHull(p) hh <- convHull(p, "NAME_1") rr <- minRect(p, "NAME_1") plot(rr, lwd=5, border="gray") plot(hh, "NAME_1", col=rainbow(10, alpha=.5), lwd=3, add=TRUE, plg=list(x="topright")) lines(aggregate(p, "NAME_1"), col="blue", lty=2, lwd=2) } \keyword{methods} \keyword{spatial} terra/man/xyCellFrom.Rd0000644000175000017500000000675414201035750014660 0ustar nileshnilesh\name{xyRowColCell} \alias{xFromCol} \alias{xFromCol,SpatRaster,numeric-method} \alias{yFromRow} \alias{yFromRow,SpatRaster,numeric-method} \alias{xyFromCell} \alias{xyFromCell,SpatRaster,numeric-method} \alias{xFromCell} \alias{xFromCell,SpatRaster,numeric-method} \alias{yFromCell} \alias{yFromCell,SpatRaster,numeric-method} \alias{cellFromRowCol} \alias{cellFromRowCol,SpatRaster,numeric,numeric-method} \alias{cellFromRowColCombine} \alias{cellFromRowColCombine,SpatRaster,numeric,numeric-method} \alias{colFromX} \alias{colFromX,SpatRaster,numeric-method} \alias{rowFromY} \alias{rowFromY,SpatRaster,numeric-method} \alias{cellFromXY} \alias{cellFromXY,SpatRaster,matrix-method} \alias{cellFromXY,SpatRaster,data.frame-method} \alias{rowFromCell} \alias{rowFromCell,SpatRaster,numeric-method} \alias{colFromCell} \alias{colFromCell,SpatRaster,numeric-method} \alias{rowColFromCell} \alias{rowColFromCell,SpatRaster,numeric-method} \title{Coordinates from a row, column or cell number and vice versa} \description{ Get coordinates of the center of raster cells for a row, column, or cell number of a SpatRaster object. Or get row, column, or cell numbers from coordinates or from each other. Cell numbers start at 1 in the upper left corner, and increase from left to right, and then from top to bottom. The last cell number equals the number of cells of the SpatRaster object. row numbers start at 1 at the top, column numbers start at 1 at the left. } \usage{ \S4method{xFromCol}{SpatRaster,numeric}(object, col) \S4method{yFromRow}{SpatRaster,numeric}(object, row) \S4method{xyFromCell}{SpatRaster,numeric}(object, cell) \S4method{xFromCell}{SpatRaster,numeric}(object, cell) \S4method{yFromCell}{SpatRaster,numeric}(object, cell) \S4method{colFromX}{SpatRaster,numeric}(object, x) \S4method{rowFromY}{SpatRaster,numeric}(object, y) \S4method{cellFromRowCol}{SpatRaster,numeric,numeric}(object, row, col) \S4method{cellFromRowColCombine}{SpatRaster,numeric,numeric}(object, row, col) \S4method{rowFromCell}{SpatRaster,numeric}(object, cell) \S4method{colFromCell}{SpatRaster,numeric}(object, cell) \S4method{rowColFromCell}{SpatRaster,numeric}(object, cell) \S4method{cellFromXY}{SpatRaster,matrix}(object, xy) } \arguments{ \item{object}{SpatRaster} \item{cell}{integer. cell number(s)} \item{col}{integer. column number(s)} \item{row}{integer row number(s)} \item{x}{x coordinate(s)} \item{y}{y coordinate(s)} \item{xy}{matrix of x and y coordinates} } \details{ Cell numbers start at 1 in the upper left corner, and increase from left to right, and then from top to bottom. The last cell number equals the number of cells of the SpatRaster (see \code{\link{ncell}}). } \value{ xFromCol, yFromCol, xFromCell, yFromCell: vector of x or y coordinates xyFromCell: matrix(x,y) with coordinate pairs colFromX, rowFromY, cellFromXY, cellFromRowCol, rowFromCell, colFromCell: vector of row, column, or cell numbers rowColFromCell: matrix of row and column numbers } \seealso{ \code{\link{crds}} } \examples{ r <- rast() xFromCol(r, c(1, 120, 180)) yFromRow(r, 90) xyFromCell(r, 10000) xyFromCell(r, c(0, 1, 32581, ncell(r), ncell(r)+1)) cellFromRowCol(r, 5, 5) cellFromRowCol(r, 1:2, 1:2) cellFromRowCol(r, 1, 1:3) # all combinations cellFromRowColCombine(r, 1:2, 1:2) colFromX(r, 10) rowFromY(r, 10) xy <- cbind(lon=c(10,5), lat=c(15, 88)) cellFromXY(r, xy) } \keyword{spatial} terra/man/topology.Rd0000644000175000017500000000246514201035750014443 0ustar nileshnilesh\name{topology} \docType{methods} \alias{topology} \alias{makeNodes} \alias{mergeLines} \alias{removeDupNodes} \alias{snap} \alias{makeNodes,SpatVector-method} \alias{mergeLines,SpatVector-method} \alias{snap,SpatVector-method} \alias{removeDupNodes,SpatVector-method} \title{ Vector topology methods } \description{ \code{makeNodes} create nodes on lines \code{mergeLines} connect lines to form polygons \code{removeDupNodes} removes duplicate nodes in geometries and optionally rounds the coordinates \code{snap} makes boundaries of geometries identical if they are very close to each other. } \usage{ \S4method{mergeLines}{SpatVector}(x) \S4method{snap}{SpatVector}(x, y=NULL, tolerance) \S4method{removeDupNodes}{SpatVector}(x, digits = -1) \S4method{makeNodes}{SpatVector}(x) } \arguments{ \item{x}{SpatVector of lines or polygons} \item{y}{SpatVector of lines or polygons to snap to. If \code{NULL} snapping is to the other geometries in \code{x}} \item{tolerance}{numeric. Snapping tolerance (distance between geometries)} \item{digits}{numeric. Number of digits used in rounding. Ignored if < 0} } \value{ SpatVector } \seealso{\code{\link{sharedPaths}}, \code{\link{gaps}}, \code{\link{simplifyGeom}}} \keyword{methods} \keyword{spatial} terra/man/merge.Rd0000644000175000017500000000652414201035750013666 0ustar nileshnilesh\name{merge} \docType{methods} \alias{merge} \alias{merge,SpatRaster,SpatRaster-method} \alias{merge,SpatRasterCollection,missing-method} \alias{merge,SpatExtent,SpatExtent-method} \alias{merge,SpatVector,data.frame-method} \title{ Merge SpatRaster or SpatExtent objects, or a SpatVector with a data.frame } \description{ Merge SpatRasters to form a new SpatRaster object with a larger spatial extent. If objects overlap, the values get priority in the same order as the arguments. See \code{\link{classify}} to merge a \code{SpatRaster} and a \code{data.frame}. You can also merge SpatExtent objects. There is a also a method for merging SpatVector with a data.frame; that is, to join the data.frame to the attribute table of the SpatVector.. } \usage{ \S4method{merge}{SpatRaster,SpatRaster}(x, y, ..., filename="", overwrite=FALSE, wopt=list()) \S4method{merge}{SpatRasterCollection,missing}(x, filename="", ...) \S4method{merge}{SpatExtent,SpatExtent}(x, y, ...) \S4method{merge}{SpatVector,data.frame}(x, y, ...) } \arguments{ \item{x}{SpatRaster or SpatExtent} \item{y}{object of same class as \code{x}} \item{...}{if \code{x} is a SpatRaster: additional objects of the same class as \code{x}. If \code{x} is a SpatRasterCollection: options for writing files as in \code{\link{writeRaster}}. If \code{x} is a SpatVector, the same arguments as in \code{\link[base]{merge}}} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{list with named options for writing files as in \code{\link{writeRaster}}} } \details{ The SpatRaster objects must have the same origin and spatial resolution. In areas where the SpatRaster objects overlap, the values of the SpatRaster that is last in the sequence of arguments will be retained. } \value{ SpatRaster or SpatExtent } \seealso{ Combining tiles with \code{\link{vrt}} may be more efficient. See \code{\link{mosaic}} for averaging overlapping regions. } \note{ You can use \code{merge} with \code{do.call} to merge a list of SpatRasters (see example). But note that if the list is named, these names are used by \code{merge}. So if all elements are named, there should be one element with a SpatRaster called \code{x} and another one called \code{y}. For example with \code{names(x)[1:2] <- c("x"m "y")}. You can also removed the names of the the first two elements (assuming these are SpatRasters) with \code{names(x)[1:2] <- ""}. } \examples{ x <- rast(xmin=-110, xmax=-80, ymin=40, ymax=70, ncols=30, nrows=30) y <- rast(xmin=-85, xmax=-55, ymax=60, ymin=30, ncols=30, nrows=30) z <- rast(xmin=-60, xmax=-30, ymax=50, ymin=20, ncols=30, nrows=30) values(x) <- 1:ncell(x) values(y) <- 1:ncell(y) values(z) <- 1:ncell(z) m1 <- merge(x, y, z) m2 <- merge(z, y, x) m3 <- merge(y, x, z) # if you have many SpatRasters make a SpatRasterCollection from a list rlist <- list(x, y, z) rsrc <- sprc(rlist) m <- merge(rsrc) ## SpatVector with data.frame f <- system.file("ex/lux.shp", package="terra") p <- vect(f) dfr <- data.frame(District=p$NAME_1, Canton=p$NAME_2, Value=round(runif(length(p), 100, 1000))) dfr <- dfr[1:5, ] pm <- merge(p, dfr, all.x=TRUE, by.x=c('NAME_1', 'NAME_2'), by.y=c('District', 'Canton')) pm values(pm) } \keyword{methods} \keyword{spatial} terra/man/zonal.Rd0000644000175000017500000000370514201035750013710 0ustar nileshnilesh\name{zonal} \alias{zonal} \alias{zonal,SpatRaster,SpatRaster-method} \title{Zonal statistics} \description{ Compute zonal statistics, that is summarized values of a SpatRaster for each "zone" defined by another SpatRaster. If \code{fun} is a true \code{function}, \code{zonal} may fail for very large SpatRaster objects, except for the functions ("mean", "min", "max", or "sum"). } \usage{ \S4method{zonal}{SpatRaster,SpatRaster}(x, z, fun=mean, ..., as.raster=FALSE, filename="", wopt=list()) } \arguments{ \item{x}{SpatRaster} \item{z}{SpatRaster with values representing zones} \item{fun}{function to be applied to summarize the values by zone. Either as character: "mean", "min", "max", "sum", or, for relatively small SpatRasters, a proper function} \item{...}{additional arguments passed to fun} \item{as.raster}{logical. If \code{TRUE}, a SpatRaster is returned with the zonal statistic for each zone} \item{filename}{character. Output filename (ignored if \code{as.raster=FALSE}} \item{wopt}{list with additional arguments for writing files as in \code{\link{writeRaster}}} } \value{ A \code{data.frame} with a value for each zone (unique value in \code{zones}) } \seealso{ See \code{\link{global}} for "global" statistics (i.e., all of \code{x} is considered a single zone), \code{\link{app}} for local statistics, and \code{\link{extract}} for summarizing values for polygons} \examples{ r <- rast(ncols=10, nrows=10) values(r) <- 1:ncell(r) z <- rast(r) values(z) <- rep(c(1:2, NA, 3:4), each=20) names(z) <- "zone" zonal(r, z, "sum", na.rm=TRUE) # multiple layers r <- rast(system.file("ex/logo.tif", package = "terra")) # zonal layer z <- rast(r, 1) names(z) <- "zone" values(z) <- rep(c(1:2, NA, c(3:4)), each=ncell(r)/5, length.out=ncell(r)) zonal(r, z, "mean", na.rm = TRUE) # raster of zonal values zr <- zonal(r, z, "mean", na.rm = TRUE, as.raster=TRUE) } \keyword{spatial} terra/man/rasterize.Rd0000644000175000017500000000636614201035750014603 0ustar nileshnilesh\name{rasterize} \docType{methods} \alias{rasterize} \alias{rasterize,SpatVector,SpatRaster-method} \alias{rasterize,matrix,SpatRaster-method} \title{Rasterize vector data} \description{ Transfer vector data to a raster } \usage{ \S4method{rasterize}{SpatVector,SpatRaster}(x, y, field="", fun, ..., background=NA, touches=FALSE, update=FALSE, sum=FALSE, cover=FALSE, filename="", overwrite=FALSE, wopt=list()) \S4method{rasterize}{matrix,SpatRaster}(x, y, values=1, fun, ..., background=NA, update=FALSE, filename="", overwrite=FALSE, wopt=list()) } \arguments{ \item{x}{SpatVector or a two-column matrix (point coordinates)} \item{y}{SpatRaster} \item{field}{character or numeric. If \code{field} is a character, it should a variable name in \code{x}. If \code{field} is numeric it typically is a single number or a vector of length \code{nrow(x)}. The values are recycled to \code{nrow(x)}} \item{values}{numeric. For when \code{x} is a matrix. Normally of length 1 or nrow(x). The values will be recycled to \code{nrow(x)}} \item{fun}{function, summarizing function that returns a single number; for when there are multiple points in one cell. For example \code{mean}, \code{length} (to get a count), \code{min} or \code{max}. Only used if \code{x} consists of points} \item{...}{additional arguments passed to \code{fun} if \code{x} has point geometries} \item{background}{numeric. Value to put in the cells that are not covered by any of the features of \code{x}. Default is \code{NA}} \item{touches}{logical. If \code{TRUE}, all cells touched by lines or polygons are affected, not just those on the line render path, or whose center point is within the polygon. If \code{touches=TRUE}, \code{add} cannot be \code{TRUE}} \item{update}{logical. If \code{TRUE}, the values of the input SpatRaster are updated} \item{sum}{logical. If \code{TRUE}, the values of overlapping geometries are summed instead of replaced; and \code{background} is set to zero. Only used if \code{x} does not consists of points} \item{cover}{logical. If \code{TRUE} and the geometry of \code{x} is polygons, the fraction of a cell that is covered by the polygons is returned. This is estimated by determining presence/absence of the polygon in at least 100 sub-cells (more of there are very few cells)} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{list with additional arguments for writing files as in \code{\link{writeRaster}}} } \seealso{ \code{\link{mask}} } \note{ To update existing raster data use the output of \code{rasterize} as second argument in \code{\link{cover}} } \value{ SpatRaster } \examples{ r <- rast(xmin=0, ncols=18, nrows=18) # generate points set.seed(1) p <- spatSample(r, 1000, xy=TRUE, replace=TRUE) # rasterize points as a matrix x <- rasterize(p, r, fun=sum) y <- rasterize(p, r, value=1:nrow(p), fun=max) # rasterize points as a SpatVector pv <- vect(p) xv <- rasterize(pv, r, fun=sum) # Polygons f <- system.file("ex/lux.shp", package="terra") v <- vect(f) r <- rast(v, ncols=75, nrows=100) z <- rasterize(v, r, "NAME_2") plot(z) lines(v) } \keyword{spatial} terra/man/figures/0000755000175000017500000000000014201035750013735 5ustar nileshnileshterra/man/figures/logo.png0000644000175000017500000010616714201035750015416 0ustar nileshnileshPNG  IHDRq4<sBIT|d IDATxmp[ם?H($"5%mJ:ήHU#)j[z3v\՛l;qU:IS6{gUglUT?Iz3SI*lgXtbdlP = q{9離:{,s~+C{:$i, bCGA+K"" @ߝS,&ED HU ,N..)O߽@5wxt_ [*- v_T*^ OJ..yo}"cuH|AY'BZJՒ4}Q䧲T"#4HtచbI^)O{cԏ;D-8T*M.J9Y\8OߝT=@m` J%yaCx!<܉0!DnU*&E^맞S=vT*m`ܙx7_Q=@eTyFTuy_#8C UE5'Bh뽇ZJ" /җ}"@~=Ԋ P+!P?!\D^%@ BރsK0z./ DC=C_E{} p!lDA?%~З"C_G{0} !,%6/"` T{'6BK@e,C_!D{KMFVЗ%E/|lC_O"8!DCA=z`ї'BO{} MЗB{p} =ЗBG{p} Kx!ƒ=Gԣ/} "Dx={}З} !Dx={}ї} Dރ=9KG_0} Kazz/ F"Dރ=З} "4GAKG_{P} K!zzE_B%E={ї} "4@AЗP^{PZ%ԣ/B"@`} MЗP2zz} =ЗPzz} Kz{8z%Cp={&K8zzPK8a#zz} K8az{芾z%E={莾&K؂Q#zz0 } =З!"zz0} KԎa=z%#DTރ=&KT zz z/6B =KG_bu;{PKKG_be=/ }zK,mzXC_B=> ԣ@}K羄B={%4þ/B={%৾C={%K_³!ރzPz^Kx.D{Ԣ/ %<"=z/%@їPK} C=`y/adz& K"=@_B&%@o/i} C=%3/mz } Mhޗ.D{tKh"=} tKh"=Gz:%zzA_B%zzjA_B*zz@_B=U} B=C8zn%,]$zpk!=7їPT*MK{opN;@MAtI 6UDCck_',R*Uw@4;+&.ԑkC{:MǶj{:/VIJ' ٽ1wiKj{:/VT\\̏$l C{kl u=ЗPT*M66;v-!bݟ-@p=qRj P?y}CCTD^uP=z K(?y Hy XCvPXz㪇&OHf>zЗPPg ؚCw{X#?yR0p~RɄa D_]Rjcc`֎DMw56e=dl"@ 6e=wI4rƕ@bilhP_-o9D; m&<߈-=m'L8,t466 <1` +}w;$Ҿ@_cDdYKψ4|PPlgt: MA-=nQ= H`}=Uߩ ZD2 J K=jVDz%Uj ~DU!j\/=,]}clgD֯S=O }`U˚ּ{;<DK8T5˚֜b=(˖lTKSsr5|AWZ5> ,cїO ]Ϯ5Cޡ>)E_@?VxgKvԡ/Q@ T_whPej8@/Qf#V  ͖N;z/Qf#C})8>*`UX~LܺƝߗ2qVKҟ]ҧlD Zcc;KXmY:3'|OɄ# K$|Fv5Byr_}c$/_\&zH 6ۥLr1=PXbјI=}vIO"u zD2!)IϧeܤL)8?"+i"9%_x]PXH,xoK,c'O?U,%IWKb.mUoXM:?pM| %#y1(" pë-۷Ȯ][~X4v&7~=ą 92~f蛓'y\vrϼ//r߿} lWH'^uw}M$݃ez+7%Wxoi$H8ϭ?q#ge'%J8$r}9S$}9[dtψ f$[nDrJ)91ILU"ބCA;9}cE,rzx?= "Kb pܸ]oK{C@3{ Jo2ovgFgFI9:vL%#&($1}֫ etϨڥ{yÀOX t:/u%lo3"JE>cO艣r7y¹rH(,۷n>w `%A,6tɡwE?9(GOW=$DBa9|Ko/>Ģ]&N5n}u|_q`(y>`6/ܠ&יt'y܈Peb*|ڱW `_X y~Kvvɗ{RyUC+ ]U}*?3"۷7LPKu)oJ6Y8Ml`SPP7)^}ٗVb>0>ѳE#_#~z8ft&4yIJŢ%(Tw툶 C{k7SEO=SɄ}|ǵ%q$~ʳW.>3]`I&GƦDש'sz%@zV0 E?q"P^p64}Qh!ʗ{W3?H8X´,ewkٷgDؓGJuSk!5KO{s h xqD}Ί}{Fs|aPC],$b̸QvI3FTrp~3>Dp`r>yϩ x!8w\U= 6FT EkaJ"8.5Hpf#* FX_~+,VXҖ4"DpIcvQ--$f#*"}2@[GvKtɄy_&OJ"9%&ovPX¡{d黧Oٌ2gDNPr}Nۭ׏If>z(%)R'd'd7Bůόѱc"r}6zxwOqSm؏O"ɄL$2qnR!?=?'a?풁Zl[8Œ |r4_e Iy՗%FeF\ ܔ@7vF32vrL&MʩNrg/+}{FΔ+|v{Fdߞ׮׏ɑډ91&Q?$c8!)WوD2!c'**h'SH'$rgV>:@ B`;71%[}A&O:{䔼2q~ҵj8$՗]nVܹED$K$N">!'=2y~R&M^3ɬdҵK&/Lr}+o}7g۾^B|V{F\ۍi¤|/H"cd̸3.GH&/LTZsϱZ/|o|3GOUߕg#//|/v=B`؆.y`p9rGZ`;Nc'Ohuҫߖ#a /?vN 䃟"b`x&zo̒'\7S=Х³[J: DKnt "ϒpxl^X4qae9igmߩj%PDbјt@P؆.ǧKu5 G_%M249;$9e+{W> BQ&4i8kGB{}'>ʑczuj_LnN&d¥zrIgw3=;ܗOrfD$qٛ]i8[^ęĴ˼L&^9~H DOkއĵG_?zZ"X15|/EP͍ZG;Qls;KLtW|]2ƤkC-Q>wn罯Ǽ<@WuqDFP1Ayz7Cbz7˕4VH(,޸IOz$!&0c wOd/o˫U1>=KH'N`<. h;ULRw)_"w@vfBCTWL*m:S o=#oψP.PH)7v1Դ}6tɡ" dJMu@/=V=-3fDBac_v M"Kg2%UlCpH0h.nYi*^Ӟ9C`xP\[ǯe=D2!gޗD2!$$3uG_xf^3BL^the$ciqz}q•Y.nt""{2~fk~%[\Vz>#G&Gǎr=.+O5?=ە$ `8BzMǯ}뀄CaǯCFbzJ~vu<nn#|fǯK{x!@N$t S2vBӮ#|Ot:߸~15oЋYFPϼ5c'Oz(jϹeXDBǯW}׆!A` 4"}}]O<a" wo,_Z;=#Z͜""dkq}I瘅@`;ezNؓ[$C hōSU:# UWvC,%#oψ>3.}S&O=C}]u/(/80pe&]2v6DBa翪l 8r5(ޑhց7LF&.LTrJɄ$SO/z<vI,>mYm$'l}]?PD9yg 3O7|gUH8(M_^&H@|Z&Oer,%?9؆.9t3bkNǔ5auO<xM׮vɗ{ReHhO=+ #_mJ]|kŁJN'yk99/eedӒH&n[j %^'}=%]۾@uO˷6 qНkŁդ2~f\)pX- vjr&K$[}aY+'lA30 !+&O/>CXC9H}( H!Dp A:lZ2Af#TUM\XTaW5 DpI7"!`A#_󓪇dAD"9%O 믯;hf Srkx!2>:vLJ9{%H$X*؈@#_/<[ޔ7|ǯ "/u$1HN}3+q̸|!}SPUyҫlP@+Y y՗(aj)=/+2vrLP!DN"9%/|_1|F|ͳ fZi 33L~YEC2gD,Kg艣 G&coi3Yc&Y+L9 l$ۧzX:}f\N1Fx3S;yB HNI"yBNXKvvC02 I$80qp- ]>@ B` )v1:DrJc$.۷+>K$v| 'e̸LS2&1pkb`77&T#_.9Ʉ՛ƻo9^fG`]%ՃoV=I׆{7K,XK¡DBaEcUFz>#̜LMO]IH"9%&%10&4* lxoĢ]p("hl͠II$d_NO8oU. %ZYc!`z`9Jg2ܬ 3s"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB` !%"XB`IP`VٶmX[Nikd\vU&'~x !5kiiʎevK4-s֛LBj)DUG%[~%:adnb6,@ȶXM*yU Bߟf6Fg!ʘ諐/H:^kRWG>YOwW]V|2+Ug!fgIXtaD"|D'vg:þ}\!_X,2"D.OǧqK?Xԅ)K_?;s5:=g#F=z}rԜs gGq>Y2?=Wq\>`e$de~nDճbA&n_~6)LJJŵSpoԻ~,?[kK׵$)YAgX̦%{yB O'[#`]Zj]?G5 v >,D]˱Oخ/oliTMLVRɔ R,5*LVDxYՄ;1~|=Fuurٵ̵f3W%qce7f$},30!TBgpege÷t]˄YOKK Ob!Pk)5*5KV&#DxY쥉Iz⽚Wg#L(knie6G\Zҩ9|m֚%+2}9ho!DxYgʊdlb|-tjΑl ;SsU͒e3Y+PBG%:ٴdf#LݞU>AÀ cKS,Y|N_N;`!ƒTxҩg!n$EO941CYD7v2;3Z 7u-˻!ƒTBUł/Z>FT( jS,CMjrk\7 K5}f#@ٵZC-j|R!Dxb.mk ܩؘ-]0-ځ:XU瓒5P=BǼ??#)dᤴXPBjMgͫcsn`OJ@u3;;#KRJ]i-WbYzzsC(3 T-/:55aeJ(Y!DxЎ$m%7uk:5 Q&r?z3<,TVsc]p ZĮ@x!c"!ogٯgg vnz-5Ν5^+v| RzSb *ILq"!PurzgXL"UυٺX\ƶ[KG2X^ޯ~.shT~|N&ή DDJł%e-Yt#8!Tev%kqL] 7" VK([ٷ<%?^l1iIO'f9Mo??*7mmυ(sxJ|FNkߥSsZ+Qpԅ)C`a:3V$p-cDVtJ 饛@CPCY).n<]u$NH.q r3D;عa x~jy=Ssi_z(pX:5'y fK0T="KgEqՄ#բT,msw# Gw)[#  ~jyRIK_!_*$fuD뚅(?nD1\lp'TAD ʊd`W*" g}N1隞 YXGTb՝Y6v[̦%7}e6B=oLE wH*%k!0V[RA=KB:e\(wXF="rC\lͳ[;w=|*eo麖b(3^=I2u%g8q\y)Jy, ғkЁ]+\K:ڥł2?1ԃm gMs|]ԕKր;A입S<A5"ƥǝ;nO}?pN d%mCMt.3mK׵\K5L t+SW2P[Xx. iAԣ}c!"=+&WW*䥘-LWȋ EsI$gzɉer}YlPkHܿ)-$hvm;~iPI!_IO2SAZBm9 })ɦUcMRIJ%PĹ|&Bj͆oYپy4ݝ% ʳg+j9Xm[{an;%u-_MkNO" i )/{MsI>r]>[Qϖne闗vfEXdW%}zqz:a3]oꕎuss\7hVwWיZRɫeS{:LֳX !Bs֐-a` Жf*UN2!+9#3~KjL{d)?1L] K' oeֳŕI)s8%vjk:|fE6eaRWRFBq5^xax]'Wi IO]H^rFT\tˊ2#:8if#l淓M(J$qc_=. !d Dh̉尜=4XŜ;(%?cϮS-FhL±g$ud3YI%OleJ(Yr`9Ωz-cݲp5avo/,DIKVd3YzZ5)f!lZe[rTZpg+Y_۲TsK+[.FsWIL{vYeJ d߬>}6f!oo7bG;:u&wYT*Ϟ}azJ:kHkH&~uZn[Z̻zrh4wz?idl }wK>dSho/76KC˪\H{D ^)SW2;sMBB>xo"kնo&}|N{ܩb.ku g$+ IDAT8[Sx#y뭟 l -wФW""kii۰ވpjƗwmFnRk!D˩lOl~aͯQ͙Y̦X@?i[D \`}ů- 6-mo._ S&rsOƕ?W4>'nJV\n\z(qj X'.QMKeu!7}QZ~׹5gm}Z9%/I.yIDD[#7Si ŅKwB =3ʼ}v暴mh3j6b^x2u%+)3s O&GsIk t;6o`ScXH^\K촘MK!B:4 SyC[{yq=ietjNd3YI~߼^b!BN kհ$w]bA2gm N1 Qm=[= Ϭ>7I'4~&1c^ 0s T^up-^1f$sግR~ IL818Zbh얯~(SWb!B,'+9ub6-dj^(axף~s!_{y'L] 'YK7ƪyTvIyyWߒVNIG2ےK^tlL*l߼MazDSX_,er҆ѸoeJ8^ 5Bh<HUڭ6jhJc(rȋM2e@N~͎'uׅml&+LֈݚVX,LbS}P=MJv* 7v4ZiW#u%:%@E{ Wfl}=' d "qz 쳴nLĽ`,?ȕ‰NBvAuv'/0!!D(B0Xߩ25V׹uz#7?⩯8B,g`|gˍLZ8:l{af|Afg܊ :?`-4Ӷaτ55î8tЮԫmŢ||c9朜?sN&!D,ePو^x%9$*5KӖ~«% SdX,JXtjN\J"D)(SkdO[E)ϙk7-_u035zaҩ9ɭ9HXCpy>覬q;]uy.EC0w|RC a !E<췭'N'&q&[E]٧_ m%Bh6[俿h'pgٙkҶM=+l!U,hh֦e Vi\`T+ U=H%J="&nCMƻ炥%BNxڣH鱌C~u-ӗҽkܙkgS"$ҾnٯIXHWOListrRblrp4p?͚oYaobK׵-_ܖ>u5mJw֯bQ J#D8'~n Zu&D:CRAӝP Jf#D8={V NyNyª^?-c.;g٭l"i q`b )fgBnm)NO{uiǮe t/YئWnb kO8RɺAڣIMA{.qs6"u%zEm 8LVfg~]T*+<\~-7vH)(̚7mLΥQ髱)(Ɗ -Ҷa}Msѽ|&AFggf.LIqܠzԕDi#BD8X01 xK#*Ma++I=.DnU@P!‚ f!C%kt^=*ÊbXg7K֦,Q!?-IsI=2腛[7R, Z/"iirQ6m^J"rmb|K7n|šѨQftڴrJyc,+^ ?M9{邴Ɏ<8KO O~ èLbZ4;sM"ini^kө9er.=LVҩ9MY5噂eJfgIh]HZíKDTYXqf#tADDR_?a-U&Ԝ{MeR>IT2ZNM(SWBZBcɟ}9{ˣU7o3d՛[TO=ɛ%k?ה!D!f!PMIVc6Bw&M jkM+bܔ`^\ B*f!̺:Yy_5?{K#BlX{T0R$J'vC凛r3ۥN皒U `yjYNJr *fz)?ljٙknUe]vŎ,qDZC,-B-goP/J~uKX;Js+WnLz'n oP=qK_w)Y@ԅ)C[`K|~! pJW=%@cƑ衴XR=_!D Wz6ޥz0{F>NZ?|d6Bw:ө9TóF-@-"%/^SO:zF IK3ŝ㎴GdftټBGl +/k+JtAL~$[<"i[9wcIV^\U>5?usfkV[Z^k;pXkK׵w{ٜ?~c6NꎙČtG[ҩ˾&3;/%wihhP%.$M-R2qoޢÎs0$" %r"DPkJՒzIXo}K>~[Q_+TRQś(,%I\s3}A\r{em"}{+Fu陴ēbYT C*B^NךfeзZPz)D]ܑhoomK<)[>V%!2rH 3_ʙv[XnK ,Ʒ< [1vrt l9W&*Y%Lt1J Ǻ@C9uHKE"kYֻ-9vk*c#]ABK!˒ IHf{f0ܣ& mGnfrp?MVm?~ SS)غeʻ{IrG 6?;oLHXveI8v0*,$Y+Np3ba)A@'+vEJc3eIlKYm,+R9udpkgҏ41D.Pt6X ڝ{"tw&=ɺRɷjO;M׳QѨU}qsg=/_|"kx+Ch+]م9uc)x;#|]gҒJbQ~ڡQɫ݁܂+"k~8CY9岫X*ʹw?Z Gdh'#]a۶,T/Y~y-FNǏF@{+Q^cZ#_Ͱw&^i v]R$~z%Cˡ^#_^W(=\hۑ^7jGuVw]#ZvϑW5wMȝ~N4ڏ@o|ƯSYl۶%ůIOrBn˯yǞN4έ9*4zʍ__хӻA5ʧsDq` rL=5;#G>WQh8"9*{#xCd @\T.D?WhdItJ2@x#xCd  W:U~[T/p Np# slӹ@ ' C@ \,F)K &ggT/przFOy{DA D!]kZY"k<{#UlḰYu^Euw!k;Gn#_TdݳMBV`~{Ʋ#OZ.5"vKXrWxNiLw?:%o#(OuV͇ڳK3i)KZpDMW;A@km4h$55idͯGY;CGn#_Td =@Hak1,s D|"_Srp0'.2_{x|y]˘z=g.aޮd 98k}ALL1Zvp'[XHܹ7WXv RFE5|\G9" PW?7jO @d"`+#l*x5fm[iVrwpf fBԎ|f/DZc:_C`05_\Y(`.+%)ӎ-b{hT]b1lwCG^>z r<[~Q'n;T~Tb=J@ +Z>jva49';%k7{oV^Ӆ#aV riGn#_@d pRRS O+z!]#Bvބ\2P"k;fGNMzR{"< 0.\.Dj"k;aAPz!"!:Y9şǢKE|5Dovٽ Ԝ%!B^Bk|1DeukLx#_ 107YCtaO3@BlzZcrȗ׍?ҵ~_P"k¶@>S!vCѧQ5wMȝ:Ƣ~3^˦2|JwACdv!P囝Sݏ̻X,ʙ m9s!8u< ]ۓ},Dڢm|~bjc@\VX(H6ūN|o9L2V=ﰜe爩dzkLqC!= DD|y]^8Ģ 馽JT3NѪ.{Ǧ'U/P?^qg#ȗO2Q{CR,wȗ'vo w|aold 9)s`pECB'&9svU?sK+ 5ܔM=D֭c+t ynb(_0/Fܛz=(ILJBY!ׯM>7+ ˨zGn`* s9y8`:nn QpX>u@2pϙ~X*ޮr`^ˀ$w5LZlV #1DQvJC2pSnyU:/s|D0y?ٺ-!.V88F'&g'b(~߁N,Kv%I " ΡT/a]N<7GN8F߹7!wNgv̤LgU/>%]Ѳ{3]wnxѬ7'y!ٴoiW G뗮N}okL:я3wMe Dd8l5&}cj'X*ʩgT/㡑/;*쌜яM "R)WD֍a@ˎ>1OM785ͺO?6I "0D%p It8Wv^+t~]wJ39-"1D%>%'সsoB+?^\֮pC4Q;z 7?R#0Di{~'&QʏWC\|-Uʪ@<1yT(Yׁ!M=ґQuW_,hg v8[|1D)Ai}rꬷG)O?g^* *K=43uLpxʏϻOrkr\2(%%zsa@N<%l'A+|aQ~Ow6iU/"aٶkeh_hGMHͼ)G~3?UsP;;-_XS|aARh ݃e1 RUrDDdL#n=G$9f"аYoBHͥY9?g]_%;S IDAT<^yJъr,'n̩LVܢz 91DX%d܁K h?];/;%*㋟$uSzJv9ㆈ|aARLg8@k hXR/.>iW{G|:X*nG?n>zCzބݿN}Od_HMͩ^Qץgӎ~VĶm"`|:'E0Tʱ-rEsx ) ),}KkgaWmo̦2O%̑XǦe>h:>7YٹgWKG٥gض-ٴlߩib@o WL># )u at~n+?ɦ|&𪜕O$"19~ Ecg8 (,ddfXg]ɯ' ;>3D=JeI(ÄޟJ]F EغEm~|:g| Z\p$,v.tR2ʏ$%EkbNM3L@[m&doFTg^6'8fYU/mbIsbUn|:'9gJRx/YOq([% ^o~JH GŢ% hŶmedoݺ?DDv۹'zE^m[ gbYO! /nR)W$} ҳ[pUq& {yݵG2cab_ yu ܂TU̒u6'oY?U(/K_zXxsͧrE7r$[q~hKGOȷzdgB #X.tjZ Ac//&{MDd]{P(qf+2? 俼Nm{ݧ񩩔 ~mZJX&n!5TEcaT*\a=-?yXT۷+N[ZfIMcm@N.:  (vk}wDV .~lU0CJZ%[tnymr,][U/8ͶĶ@ob1YZZ|aA`v _ܻuﺈnJ6+2{k*ޟ|&/vnf'x tN≸oi|:J5塓 @_ H&qr뚌O+^tWX(Hz6-E.&}Z_|۵~|_D_iZ^B?tNrBl).5p$|AFH Ԏ=2xH];vCgU&;""e-"4O礸PxSۓhٴ%Za tNڷǺ3W# ˋGys" }""269.7d|r\8)lۖl*+ٹL^mdؙKf#aInOʃyI [Y%O-rEcg!(U,K:>`YmCbd8w=5d!bjTض-ٹ$w$%DmK< lMb@$ 98^wؠ61t>k̃ ==4Ǯ[?o_sxs]mVpݛH@#OsQ>,q1yeeƚNMKTԴL/-U*˧{{9Dъ-˓oS܍[؞%nGT2_5BtYoBd!݈KR$O 햎-,Kvſ X]dr^jCl[n۶Z" "F8^y~{m*˲$]s ⸵,EbG?)iQ?> z{!BD+/ܲ,䚂^1rEޜP /x݃sֺb>}.~تʶmY-Jq(-btn$5rz*/=!=e@,92xH )BAfJf6CB!{]l:Dܻu=}ݡ~+MeRYh,0܂gU/Q)Wj$S-?pLV @a۶OKjrN}p].?m6"DDiPHR.d1(]UUǧxOKٽUBMy;^am[2s;#EN]r҃ɯ'6}[C,b}ʰ&zop+TڝnP32:vC޺f)Otn_p‡|Ϻv"D_kzbpWH$r%U?.(Ov߿X$&{X,];vsO?+GI2‚ fG[~qo޻?|bpUP7+LN2`A=򕓘NM˅/.՛T/eM .'{ޡpWP{"ժe *Ķj$& q߿a?1lض^Zjz:;{ڬKf wZ GnKGOȋG9x&kv'٭i(NUA~B:9v_ ~][ lvّaI{pSa ٴymWm;>ko#7+ :êK^mVz ݸՓr5Rݛ>z|sA27t^ !$ tjvu޲7[فqzN|Œ,D}KoC/Gr?d)2nDMw'iXͱ!Bd&˲?`PϽn4DpKzvJGge4G|hB(|2#푘t@_?1Wo^+=;AV+0!B᥿B:5KOCݛl'o  =z卓K,SrP(25?ʠЈD>6F/. B#_=$5 2ǦKÃd֨oޒ|^R˶/.}pOخ "Gڶޤ;0DTdzx|22-`w֨QK ,ۖۖeyԅmn}`{{j˲EBϻJ"TV*%ƢbE,n[|CVnX1@e:5-ӯdv /E!$\Fbј$;&¢oS^Z^w󳸺sϬ9K8;ٹS~N%'=I:pL2y ľ}7 ُiY,,^N`ygCD zQ)W{Z_꧋eɮ=}-0_|v4ȰV W"1߿O<&=h__տT:F<"DOp ~.c%!B+T(75,KVp$,[mzy%rzJ2_቞:pLRxAvU޲_8ytk 5+h_U=V]z47p~}=zex*O@o Bl[,,?~9=|ZR*CRW.EWj9).%0@Mc\ݐgkr5Ã؝=ضܶCKZDF/D}؉h ;͉Ebrx!߿Oz{DNSWo^_zZ`wS=lD!B^Bch CDz_e˿L`Tv'CF"j%@/60D/Iow'b@ Krd<Cm2>^SBdddX>^>&1cMtzЩ{؈CDϽ%"o :'Z>t^X$}XrvFo;݃z6LkHjjNc-݃x L+_QCs~k.wNxAv1jyik.U%ȂK %t;jgzbZs sd\Š7/=zxE)`Fn;+v'Eݻ9DKK8q۳eYNHlK+ӟmےL5c.[%IJ,W֚Ã]@_?CC@ѯdteΡ{7ùTYF5q!y چK2_k݉}=ʠ(tY"D%tA/ WNJOw@\2X$|c˿{ЃF|3DK!Ƚv/4jҹEPحA&wQC/^{ W2<>\s*%≇~Cl={؈oz %xB~>_.W'Aޝ{POF|?DK^w+Lx丼ѯX9iwA~6!^B0KGOȋGO^4Q( y ~ݝ{Ѓ_jP^&9#c7dtbwA=1Dl^BpCJE!S2:vԥG}=tz{CD%@/1<GTq4hI,ĎAtchzpB2}|P*tj+JpK=q MP^H˦R2`a*5+JT"v'ԣ{hCD%@/zzSt f=5 -#/^}{GkjM]LzwAt`pzI2h`$۶+7o=(dr۲Bvԧo^0D8^B=z%)2<2,z)@S ?+rER .D<$/=! E7YRQ.}q[aBAҳi).T/%Ж-<K^j=ّa˶mIϤ%Q} P^||k04d۶dSYeĶm ,0Dx^B=z պP8dlr\Ύ MXt=x!cz0Ѵ0ye$ѴOs9;2,Wo]S)tz{P!B1z %$I{4&hLĪN]h%Atz`za@t=!B#zR/$ٙDkP*|reXSӪ4Atbzx@/($㉇ xm ~@1D^B=D=DgB[Ƥo耣Zt=!zpXQrKbyX/7AgRQݼ&Wo])^Y@`K衞^"_1<=Leڭk_{݃" E/^"O^| ,O@`6KO˛]^Yߠ{P"|^B엟e[6KZ)K#==CK[K~1LRQƧelr\ƦƹBa!z um{8Lah@="|^Bm]# IDAT/O~طT/V(etLetd<=G >G/z x)ȝq݃!" %@/pAt0KI߀ {C01Dzh丌ߐ7q+A=`c0z =K,{"@/ z וetz{@ CP^"DKG/L:{Pa%@/ RQGT/݃l^B569.~ {KG//RQ~s=z)rtz{@#"z %w%ddh= h%̓e7NB 4!MΎ ˅}@=b@%ԣ4Atp CC/>݃ztpCE/z 5ix݃^B+r5݃&^B=z w8== zu%`}t=K  %@1DszTjZ/vU@U" zz|p4݃CP^q_.V @+t=@ %8u X ݃h^BA%ҹ|xᴌNP@tz{"%z KJE%p݃3h^B=?7 %)+PCLK/D&ѱ2:~XAt0CA/zB(өi_uE!ơPO^P*ʵdtLi5=b%ӭ(r5KFLKAu/ K@}@?`/K^mےLI>S@{0DW%󪗸z|22L( lAt#zncrvdYM,$5{P~ߢЃSP=="{zhH2M=AP^P*Ȱ\+E C^Bz N\G!D/P?== "hz';%=)HXR=`D^BH0Qtz{@/^8ēhA=q *zh.vn'݃1D렗At"MKgYlݖ=CP'z %Wt=a@/h,*;vGq @%@/S=hCz %`==c@/tG!zn@8!p%݃w0D.P^*=pC2z %o0DB; %@/=Czh݃u"%ԣ@ԣ{c6C@ &%@/@! z{'@SK݃zt"K^"8@!0%At9"KG//tz{^B=z =G!0%Cl %@/?==zz{/ KG/b|^B=/%@/==z{ @KG/<a^B{L @@K^qtz{!8z %C" P^b}t=X!Cz݃1zr/Aa.z K=f"l^B t=CK݃4!@C%^At)K=@+"^B=z 8!@%s/ANaz =K="8^B=ս݃!k%SK=Gm \E//z ==COK^AtS9K= P^A=*1DP^Btz{C%Q/Q)W$={P."h^BDb RT\,KPR@{ڡ=C-K !%4tL;&a`z 1D0"^{`:ƣ)Cߠ C_nC_jt!Kkt!@ Kmt!@`K-t!@K)t!@`KYt!@K^t!^{o0D Xk!6@/L0<"`uj۟CЫC? P ۮ·,Ӗ?"g;yK~oveKu]Pm[Jemv_"^zZ>/!덪-ϻ1T10] <- NA } \keyword{methods} \keyword{spatial} terra/man/sapp.Rd0000644000175000017500000000234014201035750013522 0ustar nileshnilesh\name{sapp} \docType{methods} \alias{sapp} \alias{sapp,SpatRaster-method} \alias{sapp,SpatRasterDataset-method} \title{Apply a terra function that takes only a single layer and returns a SpatRaster to all layers of a SpatRaster} \description{ Apply to all layers of a SpatRaster a function that only takes a single layer SpatRaster and returns a SpatRaster (these are rare). In most cases you can also use \code{lapply} or \code{sapply} for this. } \usage{ \S4method{sapp}{SpatRaster}(x, fun, ..., filename="", overwrite=FALSE, wopt=list()) } \arguments{ \item{x}{SpatRaster} \item{fun}{a function that takes a SpatRaster argument and can be applied to each layer of \code{x}} \item{...}{additional arguments to be passed to \code{fun}} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{list with named options for writing files as in \code{\link{writeRaster}}} } \value{ SpatRaster } \seealso{\code{ \link{lapp}, \link{app}, \link[terra]{tapp}, \link{lapply}} } \examples{ s <- rast(system.file("ex/logo.tif", package="terra")) + 1 x <- sapp(s, terrain) } \keyword{methods} \keyword{spatial} terra/man/mosaic.Rd0000644000175000017500000000350314201035750014034 0ustar nileshnilesh\name{mosaic} \docType{methods} \alias{mosaic} \alias{mosaic,SpatRaster,SpatRaster-method} \alias{mosaic,SpatRasterCollection,missing-method} \title{ mosaic SpatRasters } \description{ Combine adjacent and (partly) overlapping SpatRasters to form a single new SpatRaster. Values in overlapping cells are averaged. This method is similar to the simpler, but faster \code{\link{merge}} method. } \usage{ \S4method{mosaic}{SpatRaster,SpatRaster}(x, y, ..., fun="mean", filename="", overwrite=FALSE, wopt=list()) \S4method{mosaic}{SpatRasterCollection,missing}(x, fun="mean", filename="", ...) } \arguments{ \item{x}{SpatRaster} \item{y}{object of same class as \code{x}} \item{...}{additional SpatRasters} \item{fun}{character. One of "sum", "mean", "median", "min", "max"} \item{filename}{character. Output filename} \item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten} \item{wopt}{list with named options for writing files as in \code{\link{writeRaster}}} } \details{ The SpatRaster objects must have the same origin and spatial resolution. In areas where the SpatRaster objects overlap, the values of the SpatRaster that is last in the sequence of arguments will be retained. } \value{ SpatRaster } \seealso{ \code{\link{merge}} } \examples{ x <- rast(xmin=-110, xmax=-80, ymin=40, ymax=70, ncols=30, nrows=30) y <- rast(xmin=-85, xmax=-55, ymax=60, ymin=30, ncols=30, nrows=30) z <- rast(xmin=-60, xmax=-30, ymax=50, ymin=20, ncols=30, nrows=30) values(x) <- 1:ncell(x) values(y) <- 1:ncell(y) values(z) <- 1:ncell(z) m1 <- mosaic(x, y, z) m2 <- mosaic(z, y, x) # if you have many SpatRasters make a SpatRasterCollection from a list rlist <- list(x, y, z) rsrc <- sprc(rlist) m <- mosaic(rsrc) } \keyword{methods} \keyword{spatial} terra/src/0000755000175000017500000000000014203000615012277 5ustar nileshnileshterra/src/spatBase.h0000644000175000017500000001726514201035750014233 0ustar nileshnilesh// Copyright (c) 2018-2020 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include #include #include #include #ifndef standalone #define useRcpp #endif #ifndef nogdal #define useGDAL #endif /* #ifdef useGDAL #include "gdal_priv.h" #endif */ #ifndef M_PI #define M_PI (3.14159265358979323846) #endif class SpatMessages { public: virtual ~SpatMessages(){} bool has_error = false; bool has_warning = false; std::string error; std::string message; std::vector warnings; void setError(std::string s) { has_error = true; error = s; } std::string getError() { has_error = false; std::string err = error; error = ""; return err; } void addWarning(std::string s) { has_warning = true; warnings.push_back(s); } std::string getWarnings() { std::string w = ""; for (size_t i = 0; i getAll() { std::string warns = getWarnings(); std::string error = getError(); std::string msg = getMessage(); std::vector amsgs = { error, warns, msg}; return amsgs; } }; class SpatOptions { private: std::string tempdir = ""; bool todisk = false; double memmax = -1; double memfrac = 0.6; double tolerance = 0.1; public: SpatOptions(); SpatOptions(const SpatOptions &opt); SpatOptions deepCopy(); virtual ~SpatOptions(){} unsigned ncopies = 4; unsigned minrows = 1; bool threads=false; std::string def_datatype = "FLT4S"; std::string def_filetype = "GTiff"; //std::string def_bandorder = "BIL"; bool overwrite = false; unsigned progress = 3; size_t steps = 0; bool hasNAflag = false; double NAflag = NAN; bool def_verbose = false; bool verbose = false; //bool append = false; int statistics = 1; bool datatype_set = false; //bool ncdfcopy = false; unsigned char value_type = 0; unsigned pid=0; std::string datatype = ""; //std::string bandorder = ""; std::string filetype = ""; std::vector filenames = {""}; std::vector gdal_options; std::vector names; // permanent bool get_todisk(); void set_todisk(bool b); double get_memfrac(); void set_memfrac(double d); double get_memmax(); void set_memmax(double d); std::string get_tempdir(); void set_tempdir(std::string d); double get_tolerance(); void set_tolerance(double d); std::string get_def_datatype(); std::string get_def_bandorder(); std::string get_def_filetype(); bool get_def_verbose(); void set_def_datatype(std::string d); //void set_def_bandorder(std::string d); void set_def_filetype(std::string d); // single use void set_verbose(bool v); void set_def_verbose(bool v); void set_NAflag(double flag); //void set_ncdfcopy(bool x); void set_statistics(int s); //void set_filename(std::string f); void set_filenames(std::vector f); void set_filetype(std::string d); void set_datatype(std::string d); //void set_bandorder(std::string d); void set_overwrite(bool b); //void set_append(bool b); void set_progress(unsigned p); std::string get_filename(); std::vector get_filenames(); std::string get_filetype(); std::string get_datatype(); //std::string get_bandorder(); bool get_verbose(); //bool get_ncdfcopy(); int get_statistics(); double get_NAflag(); bool has_NAflag(double &flag); bool get_overwrite(); //bool get_append(); unsigned get_progress(); bool show_progress(unsigned n); bool progressbar=true; void set_steps(size_t n); size_t get_steps(); void set_ncopies(size_t n); size_t get_ncopies(); SpatMessages msg; }; class SpatExtent { public: double xmin, xmax, ymin, ymax; SpatExtent() {xmin = -180; xmax = 180; ymin = -90; ymax = 90;} SpatExtent(double _xmin, double _xmax, double _ymin, double _ymax) {xmin = _xmin; xmax = _xmax; ymin = _ymin; ymax = _ymax;} virtual ~SpatExtent(){} SpatExtent deepCopy() {return *this;} SpatExtent align(double d, std::string snap); SpatExtent intersect(SpatExtent e) { // check first if intersects? SpatExtent out; out.xmin = std::max(xmin, e.xmin); out.xmax = std::min(xmax, e.xmax); out.ymin = std::max(ymin, e.ymin); out.ymax = std::min(ymax, e.ymax); return out; } void unite(SpatExtent e) { if (std::isnan(xmin)) { xmin = e.xmin; xmax = e.xmax; ymin = e.ymin; ymax = e.ymax; } else { xmin = std::min(xmin, e.xmin); xmax = std::max(xmax, e.xmax); ymin = std::min(ymin, e.ymin); ymax = std::max(ymax, e.ymax); } } std::vector asVector() { std::vector e = { xmin, xmax, ymin, ymax }; return(e); } std::vector> asPoints() { std::vector> pts(2, std::vector(4)); pts[0][0] = xmin; pts[1][0] = ymin; pts[0][1] = xmin; pts[1][1] = ymax; pts[0][2] = xmax; pts[1][2] = ymax; pts[0][3] = xmax; pts[1][3] = ymin; return(pts); } bool valid() { return ((xmax >= xmin) && (ymax >= ymin)); } bool valid_notequal() { return ((xmax > xmin) && (ymax > ymin)); } bool compare(SpatExtent e, std::string oper, double tolerance); SpatExtent round(int n); SpatExtent floor(); SpatExtent ceil(); std::vector test_sample(size_t size, size_t N, bool replace, std::vector w, unsigned seed); std::vector> sampleRegular(size_t size, bool lonlat); std::vector> sampleRandom(size_t size, bool lonlat, unsigned seed); }; class SpatSRS { public: virtual ~SpatSRS(){} // SpatSRS(std::string s); std::string proj4, wkt; bool set(std::string txt, std::string &msg); /* #ifdef useGDAL bool set(OGRSpatialReference *poSRS, std::string &msg); #endif */ double to_meter(); std::string get(std::string x) { return (x == "proj4" ? proj4 : wkt); } std::string get_prj() { return proj4; } bool is_equal(SpatSRS x) { return (proj4 == x.proj4); } bool is_empty() { return (wkt == ""); } bool is_same(std::string other, bool ignoreempty); bool is_same(SpatSRS x, bool ignoreempty); bool is_lonlat(); // as below, but using GDAL bool is_lonlat_text() { bool b1 = proj4.find("longlat") != std::string::npos; bool b2 = proj4.find("epsg:4326") != std::string::npos; return (b1 | b2); } bool could_be_lonlat(SpatExtent e) { bool b = is_lonlat(); if ((!b) & is_empty()) { if ((e.xmin >= -180.1) & (e.xmax <= 180.1) & (e.ymin >= -90.1) & (e.ymax <= 90.1)) { b = true; } } return b; } bool is_global_lonlat(SpatExtent e) { if (is_lonlat()) { return (std::abs(e.xmax - e.xmin - 360) < 0.001); //double halfres = xres()/ 180; //if (((e.xmin - halfres) <= -180) && ((e.xmax + halfres) >= 180)) { // return true; //} } return false; } }; terra/src/spatFactor.h0000644000175000017500000000577314201035750014600 0ustar nileshnilesh#ifndef SPATFACTOR_GUARD #define SPATFACTOR_GUARD #include #include #include //#include "NA.h" #include template std::vector unique_values(std::vector d) { std::sort(d.begin(), d.end()); d.erase(std::unique(d.begin(), d.end()), d.end()); //d.erase(std::remove(d.begin(), d.end(), na), d.end()); return d; } /* std::string double_2_string(double x) { std::string s = std::to_string (x); s.erase( s.find_last_not_of('0') + 1, std::string::npos ); s.erase( s.find_last_not_of('.') + 1, std::string::npos ); return s; } std::vector double_2_string(const std::vector &x, std::string prep) { std::vector out(x.size()); for (size_t i=0; i string_values(std::vector& v) { return v; } template std::vector string_values(std::vector& v) { std::vector result; std::transform(std::begin(v), std::end(v), std::back_inserter(result), [](T d) { std::string s = std::to_string(d); s.erase( s.find_last_not_of('0') + 1, std::string::npos ); s.erase( s.find_last_not_of('.') + 1, std::string::npos ); return s; } ); return result; } class SpatFactor { public: virtual ~SpatFactor(){} std::vector v; std::vector levels; std::vector labels; size_t size() { return v.size(); } void compute_levels() { levels = unique_values(v); labels = string_values(levels); } template void set_values(std::vector _values) { std::vector u = unique_values(_values); size_t n = _values.size(); size_t un = u.size(); labels = string_values(u); levels.resize(un); std::iota(levels.begin(), levels.end(), 0); v.resize(n); for (size_t i=0; i _levels, std::vector _labels) { if (_levels.size() == _labels.size()) { levels = _levels; labels = _labels; } else { return false; } return true; } bool set_labels(std::vector _labels) { if (levels.size() == _labels.size()) { labels = _labels; } else { return false; } return true; } void resize(size_t n) { //v.resize(n, NA::value); v.resize(n); } void reserve(size_t n) { v.reserve(n); } template SpatFactor(std::vector _v) { set_values(_v); } SpatFactor subset(std::vector i) { SpatFactor out; out.levels = levels; out.labels = labels; size_t n = i.size(); out.reserve(n); for (size_t j=0; j. #include #include #include //#include //#include "spatRaster.h" #include "spatRasterMultiple.h" #include "vecmath.h" #include "file_utils.h" #include "string_utils.h" #include "spatTime.h" #include "recycle.h" #include "gdalio.h" //#include "NA.h" #include "gdal_priv.h" #include "cpl_conv.h" // for CPLMalloc() #include "cpl_string.h" #include "ogr_spatialref.h" #include "gdal_rat.h" //#include "hdr.h" #if GDAL_VERSION_MAJOR >= 3 #include "proj.h" #endif void SpatRaster::gdalogrproj_init(std::string path) { GDALAllRegister(); OGRRegisterAll(); //GDALregistred = true; #if GDAL_VERSION_MAJOR >= 3 if (path != "") { const char *cp = path.c_str(); proj_context_set_search_paths(PJ_DEFAULT_CTX, 1, &cp); } #endif } /* bool GetTime(std::string filename, std::vector &time, std::string ×tep, size_t nl) { filename += ".time"; if (!file_exists(filename)) { return false; } std::vector s = read_text(filename); if (nl != (s.size()-1)) return false; time.reserve(nl); timestep = s[0]; for (size_t i=0; i &units, size_t nl) { filename += ".unit"; if (!file_exists(filename)) { return false; } units = read_text(filename); if (nl != units.size()) return false; return true; } */ bool read_aux_json(std::string filename, std::vector &time, std::string ×tep, std::vector &units, size_t nlyr) { filename += ".aux.json"; if (!file_exists(filename)) return false; std::vector s = read_text(filename); int itime=-1, istep=-1, iunit=-1; for (size_t i=0; i x = strsplit_first(s[i], ":"); if (x.size() != 2) continue; x[0].erase(std::remove(x[0].begin(), x[0].end(), '\"'), x[0].end()); if (x[0] == "time") itime = i; if (x[0] == "timestep") istep = i; if (x[0] == "unit") iunit = i; } if (itime >= 0) { std::vector x = strsplit_first(s[itime], "["); if (x.size() == 2) { x = strsplit(x[1], "]"); x = strsplit(x[0], ","); std::vector tm; for (size_t i=0; i= 0) && (time.size() > 0)) { std::vector x = strsplit_first(s[istep], ":"); if (x.size() == 2) { x = strsplit(x[1], ","); unquote(x[0]); timestep = x[0]; } } } if (iunit >= 0) { std::vector x = strsplit_first(s[iunit], "["); if (x.size() == 2) { x = strsplit(x[1], "]"); x = strsplit(x[0], ","); if (x.size() == nlyr) { for (size_t i=0; i< x.size(); i++) { unquote(x[i]); } units = x; } } } return false; } SpatCategories GetRAT(GDALRasterAttributeTable *pRAT) { SpatCategories out; /* const char *GFU_type_string[] = {"GFT_Integer", "GFT_Real","GFT_String"}; const char *GFU_usage_string[] = {"GFU_Generic", "GFU_PixelCount", "GFU_Name", "GFU_Min", "GFU_Max", "GFU_MinMax", "GFU_Red", "GFU_Green", "GFU_Blue", "GFU_Alpha", "GFU_RedMin", "GFU_GreenMin", "GFU_BlueMin", "GFU_AlphaMin", "GFU_RedMax", "GFU_GreenMax", "GFU_BlueMax", "GFU_AlphaMax", "GFU_MaxCount"}; std::vector GFT_type; std::vector GFT_usage; */ size_t nc = (int) pRAT->GetColumnCount(); size_t nr = (int) pRAT->GetRowCount(); std::vector ss = {"histogram", "count", "red", "green", "blue", "opacity", "r", "g", "b", "alpha"}; std::vector ratnms; std::vector id, id2; bool hasvalue=false; for (size_t i=0; iGetNameOfCol(i); lowercase(name); ratnms.push_back(name); if (name == "value") { id.insert(id.begin(), i); hasvalue = true; } else { int k = where_in_vector(name, ss, true); if (k >= 0) { id2.push_back(i); } else { id.push_back(i); } } } id.insert(id.end(), id2.begin(), id2.end()); if (!hasvalue) { std::vector vid(nr); std::iota(vid.begin(), vid.end(), 0); out.d.add_column(vid, "value"); } for (size_t k=0; kGetNameOfCol(i); GDALRATFieldType nc_type = pRAT->GetTypeOfCol(i); // GFT_type.push_back(GFU_type_string[nc_types[i]]); // GDALRATFieldUsage nc_usage = pRAT->GetUsageOfCol(i); // GFT_usage.push_back(GFU_usage_string[nc_usages[i]]); if (nc_type == GFT_Integer) { std::vector d(nr); for (size_t j=0; jGetValueAsInt(j, i); } out.d.add_column(d, name); } else if (nc_type == GFT_Real) { std::vector d(nr); for (size_t j=0; jGetValueAsDouble(j, i); } out.d.add_column(d, name); } else if (nc_type == GFT_String) { std::vector d(nr); for (size_t j=0; jGetValueAsString(j, i); } out.d.add_column(d, name); } } out.index = out.d.ncol() > 1 ? 1 : 0; return(out); } bool GetVAT(std::string filename, SpatCategories &vat) { filename += ".vat.dbf"; if (!file_exists(filename)) { return false; } SpatVector v, fvct; std::vector fext; v.read(filename, "", "", fext, fvct, false); if (v.df.nrow() == 0) return false; std::vector nms = v.df.get_names(); std::vector ss = {"count", "histogram"}; std::vector rng; rng.reserve(nms.size()); for (size_t i=0; i 1) { vat.d = v.df.subset_cols(rng); // vat.d.names[0] = "ID"; vat.index = 1; std::string sc = vat.d.names[1]; lowercase(sc); if (sc == "count") { if (rng.size() == 2) { return false; } else { vat.index = 2; } } return true; } return false; } SpatDataFrame GetCOLdf(GDALColorTable *pCT) { SpatDataFrame out; size_t nc = (int) pCT->GetColorEntryCount(); out.add_column(1, "value"); out.add_column(1, "red"); out.add_column(1, "green"); out.add_column(1, "blue"); out.add_column(1, "alpha"); out.reserve(nc); for (size_t i=0; iGetColorEntry(i); out.iv[0].push_back(i); out.iv[1].push_back(col->c1); out.iv[2].push_back(col->c2); out.iv[3].push_back(col->c3); out.iv[4].push_back(col->c4); } return(out); } bool getIntFromDoubleCol(std::vector & dv, std::vector &iv) { double dmn = vmin(dv, true); if (dmn < 0) return false; double dmx = vmax(dv, true); if (dmx > 255) { return false; } iv.resize(0); iv.reserve(dv.size()); if (dmx <= 1) { for (size_t i=0; i iv; size_t j = d.iplace[k]; if (getIntFromDoubleCol(d.dv[j], iv)) { out.add_column(iv, name); } else { return false; } } else if (d.itype[k] == 1) { size_t j = d.iplace[k]; long dmn = vmin(d.iv[j], true); if (dmn < 0) return false; long dmx = vmax(d.iv[j], true); if (dmx > 255) return false; out.add_column(d.iv[j], name); } else { return false; } return true; } bool colsFromRat(SpatDataFrame &d, SpatDataFrame &out) { std::vector ss = d.get_names(); for (size_t i=0; i= 0) { size_t j = d.iplace[k]; if (d.itype[k] == 1) { out.add_column(d.iv[j], "value"); } else { std::vector x; x.reserve(d.nrow()); for (size_t i=0; i cols1 = {"red", "green", "blue"}; std::vector cols2 = {"r", "g", "b"}; for (size_t i=0; i<3; i++) { int k = where_in_vector(cols1[i], ss, true); if (k >= 0) { if (!setIntCol(d, out, k, cols1[i])) return false; } else { int k = where_in_vector(cols2[i], ss, true); if (k >= 0) { if (!setIntCol(d, out, k, cols1[i])) return false; } else { return false; } } } bool have_alpha = false; k = where_in_vector("alpha", ss, true); if (k >= 0) { if (setIntCol(d, out, k, "alpha")) have_alpha = true; } if (!have_alpha) { int k = where_in_vector("transparency", ss, true); if (k >= 0) { if (setIntCol(d, out, k, "alpha")) have_alpha = true; } } if (!have_alpha) { std::vector a(out.nrow(), 255); out.add_column(a, "alpha"); } d = out; return true; } /* SpatDataFrame GetColFromRAT(SpatDataFrame &rat) { SpatDataFrame out; size_t nr = rat.nrow(); if (nr > 256) return out; std::vector nms = rat.get_names(); int red = where_in_vector("red", nms, false); int green = where_in_vector("green", nms, false); int blue = where_in_vector("blue", nms, false); int alpha = where_in_vector("alpha", nms, true); std::vector r {(unsigned)red, (unsigned)green, (unsigned)blue}; if (alpha >= 0) { r.push_back(alpha); } out = rat.subset_cols(r); if (alpha < 0) { std::vector a(nr, 255); out.add_column(a, "alpha"); } out.names = {"red", "green", "blue", "alpha"}; return out; } */ SpatCategories GetCategories(char **pCat, std::string name) { long n = CSLCount(pCat); SpatCategories scat; std::vector id; std::vector nms; id.reserve(n); nms.reserve(n); for (long i = 0; i= 3 const OGRSpatialReference *srs = poDataset->GetSpatialRef(); if (srs == NULL) return wkt; char *cp; const char *options[3] = { "MULTILINE=YES", "FORMAT=WKT2", NULL }; OGRErr err = srs->exportToWkt(&cp, options); if (err == OGRERR_NONE) { wkt = std::string(cp); } CPLFree(cp); #else if (poDataset->GetProjectionRef() != NULL) { char *cp; OGRSpatialReference oSRS(poDataset->GetProjectionRef()); #if GDAL_VERSION_MAJOR >= 3 const char *options[3] = { "MULTILINE=NO", "FORMAT=WKT2", NULL }; OGRErr err = oSRS.exportToWkt(&cp, options); #else OGRErr err = oSRS.exportToWkt(&cp); #endif if (err == OGRERR_NONE) { wkt = std::string(cp); } CPLFree(cp); } #endif return wkt; } std::string getDsPRJ(GDALDataset *poDataset) { std::string prj = ""; #if GDAL_VERSION_MAJOR >= 3 const OGRSpatialReference *srs = poDataset->GetSpatialRef(); if (srs == NULL) return prj; char *cp; OGRErr err = srs->exportToProj4(&cp); if (err == OGRERR_NONE) { prj = std::string(cp); } CPLFree(cp); #else if( poDataset->GetProjectionRef() != NULL ) { OGRSpatialReference oSRS(poDataset->GetProjectionRef()); char *pszPRJ = NULL; oSRS.exportToProj4(&pszPRJ); prj = pszPRJ; } #endif return prj; } SpatRasterStack::SpatRasterStack(std::string fname, std::vector ids, bool useids) { std::vector ops; GDALDataset *poDataset = openGDAL(fname, GDAL_OF_RASTER | GDAL_OF_READONLY | GDAL_OF_VERBOSE_ERROR, ops); if( poDataset == NULL ) { if (!file_exists(fname)) { setError("file does not exist"); } else { setError("cannot read from " + fname ); } return; } std::string delim = "NAME="; char **metadata = poDataset->GetMetadata("SUBDATASETS"); if (metadata == NULL) { setError("file has no subdatasets"); GDALClose( (GDALDatasetH) poDataset ); return; } std::vector meta; for (size_t i=0; metadata[i] != NULL; i++) { meta.push_back(metadata[i]); } if (!useids) { ids.resize(meta.size()); std::iota(ids.begin(), ids.end(), 0); } SpatRaster sub; int idssz = ids.size(); int metsz = meta.size(); if (metsz == 0) { setError("file does not consist of subdatasets"); } else { for (int i=0; i= metsz)) { continue; } std::string s = meta[ids[i]*2]; size_t pos = s.find(delim); if (pos != std::string::npos) { s.erase(0, pos + delim.length()); if (sub.constructFromFile(s, {-1}, {""}, {})) { if (!push_back(sub, basename_sds(s), "", "", true)) { addWarning("skipped (different geometry): " + s); } } else { addWarning("skipped (fail): " + s); } } } } GDALClose( (GDALDatasetH) poDataset ); } SpatRaster SpatRaster::fromFiles(std::vector fname, std::vector subds, std::vector subdsname, std::vector options) { SpatRaster out; out.constructFromFile(fname[0], subds, subdsname, options); if (out.hasError()) return out; SpatOptions opt; for (size_t i=1; i subds, std::vector subdsname, std::vector options) { GDALDataset *poDataset = openGDAL(fname, GDAL_OF_RASTER | GDAL_OF_READONLY | GDAL_OF_VERBOSE_ERROR, options); if( poDataset == NULL ) { if (!file_exists(fname)) { setError("file does not exist: " + fname); } else { setError("cannot read from " + fname ); } return false; } int nl = poDataset->GetRasterCount(); std::string gdrv = poDataset->GetDriver()->GetDescription(); char **metasds = poDataset->GetMetadata("SUBDATASETS"); if (metasds != NULL) { std::vector meta; for (size_t i=0; metasds[i] != NULL; i++) { meta.push_back(metasds[i]); } GDALClose( (GDALDatasetH) poDataset ); return constructFromSDS(fname, meta, subds, subdsname, options, gdrv=="netCDF"); } else if (nl==0) { setError("no raster data in " + fname); return false; } SpatRasterSource s; s.ncol = poDataset->GetRasterXSize(); s.nrow = poDataset->GetRasterYSize(); s.nlyr = nl; s.nlyrfile = nl; s.resize(nl); s.flipped = false; s.rotated = false; double adfGeoTransform[6]; bool hasExtent = true; if( poDataset->GetGeoTransform( adfGeoTransform ) == CE_None ) { double xmin = adfGeoTransform[0]; /* left x */ double xmax = xmin + adfGeoTransform[1] * s.ncol; /* w-e resolution */ //xmax = roundn(xmax, 9); double ymax = adfGeoTransform[3]; // top y double ymin = ymax + s.nrow * adfGeoTransform[5]; //ymin = roundn(ymin, 9); if (adfGeoTransform[5] > 0) { s.flipped = true; std::swap(ymin, ymax); } SpatExtent e(xmin, xmax, ymin, ymax); s.extent = e; if (adfGeoTransform[2] != 0 || adfGeoTransform[4] != 0) { s.rotated = true; addWarning("the data in this file are rotated. Use 'rectify' to fix that"); } } else { hasExtent = false; SpatExtent e(0, 1, 0, 1); s.extent = e; if ((gdrv=="netCDF") || (gdrv == "HDF5")) { #ifndef standalone setMessage("ncdf extent"); #else addWarning("unknown extent. Cells not equally spaced?"); #endif } else { addWarning("unknown extent"); } } s.memory = false; s.filename = fname; s.open_ops = options; //s.driver = "gdal"; /* if( poDataset->GetProjectionRef() != NULL ) { OGRSpatialReference oSRS(poDataset->GetProjectionRef()); char *pszPRJ = NULL; oSRS.exportToProj4(&pszPRJ); s.crs = pszPRJ; } else { s.crs = ""; } */ std::string crs = getDsWKT(poDataset); if (crs == "") { if (hasExtent && s.extent.xmin >= -180 && s.extent.xmax <= 360 && s.extent.ymin >= -90 && s.extent.ymax <= 90) { crs = "OGC:CRS84"; s.parameters_changed = true; } } std::string msg; if (!s.srs.set(crs, msg)) { addWarning(msg); } std::vector timestamps; std::string timestep="raw"; std::vector units; try { read_aux_json(fname, timestamps, timestep, units, s.nlyr); } catch(...) { timestamps.resize(0); units.resize(0); addWarning("could not parse aux.json"); } if (timestamps.size() > 0) { s.time = timestamps; s.timestep = timestep; s.hasTime = true; } if (units.size() > 0) { s.unit = units; s.hasUnit = true; } GDALRasterBand *poBand; //int nBlockXSize, nBlockYSize; double adfMinMax[2]; int bGotMin, bGotMax; // s.layers.resize(1); // std::string unit = ""; s.source_name = basename_noext(fname); std::vector> bandmeta(s.nlyr); bool getCols = s.nlyr == 3; std::vector rgb_lyrs(3, -99); int bs1, bs2; for (size_t i = 0; i < s.nlyr; i++) { poBand = poDataset->GetRasterBand(i+1); if ((gdrv=="netCDF") || (gdrv == "HDF5")) { char **m = poBand->GetMetadata(); while (*m != nullptr) { bandmeta[i].push_back(*m++); } } int success; // double naflag = poBand->GetNoDataValue(&success); // if (success) { // s.NAflag = naflag; // } else { // s.NAflag = NAN; // } s.has_scale_offset[i] = false; double offset = poBand->GetOffset(&success); if (success) { if (offset != 0) { s.offset[i] = offset; s.has_scale_offset[i] = true; } } double scale = poBand->GetScale(&success); if (success) { if (scale != 1) { s.scale[i] = scale; s.has_scale_offset[i] = true; } } poBand->GetBlockSize(&bs1, &bs2); s.blockcols[i] = bs1; s.blockrows[i] = bs2; //std::string dtype = GDALGetDataTypeName(poBand->GetRasterDataType()); adfMinMax[0] = poBand->GetMinimum( &bGotMin ); adfMinMax[1] = poBand->GetMaximum( &bGotMax ); if( (bGotMin && bGotMax) ) { s.hasRange[i] = true; s.range_min[i] = adfMinMax[0]; s.range_max[i] = adfMinMax[1]; } //if( poBand->GetOverviewCount() > 0 ) printf( "Band has %d overviews.\n", poBand->GetOverviewCount() ); if (getCols) { if (poBand->GetColorInterpretation() == GCI_RedBand) { rgb_lyrs[0] = i; } else if (poBand->GetColorInterpretation() == GCI_GreenBand) { rgb_lyrs[1] = i; } else if (poBand->GetColorInterpretation() == GCI_BlueBand) { rgb_lyrs[2] = i; } } GDALColorTable *ct = poBand->GetColorTable(); if( ct != NULL ) { s.hasColors[i] = true; s.cols[i] = GetCOLdf(ct); } std::string bandname = poBand->GetDescription(); char **cat = poBand->GetCategoryNames(); if( cat != NULL ) { SpatCategories scat = GetCategories(cat, bandname); s.cats[i] = scat; s.hasCategories[i] = true; } bool have_rat = false; SpatCategories crat; if (!s.hasCategories[i]) { GDALRasterAttributeTable *rat = poBand->GetDefaultRAT(); if( rat != NULL ) { crat = GetRAT(rat); if (crat.d.nrow() > 0) { if (gdrv == "AIG") { std::vector catnms = crat.d.get_names(); std::vector compnms = {"ID", "VALUE", "COUNT"}; if ((catnms.size() > 3) || (catnms != compnms)) { s.cats[i] = crat; s.hasCategories[i] = true; have_rat = true; } } else { s.cats[i] = crat; s.hasCategories[i] = true; have_rat = true; } } } } // } else { // s.cats[i].d.cbind(crat.d); // needs more checking. // } else { if (!s.hasCategories[i]) { if (GetVAT(fname, crat)) { s.cats[i] = crat; s.hasCategories[i] = true; have_rat = true; } } if ((!s.hasColors[i]) && (have_rat)) { SpatDataFrame ratcols; if (colsFromRat(crat.d, ratcols)) { s.hasColors[i] = true; s.cols[i] = ratcols; } } std::string nm = ""; if (s.hasCategories[i]) { if (s.cats[i].index < s.cats[i].d.ncol()) { std::vector nms = s.cats[i].d.get_names(); nm = nms[s.cats[i].index]; } } if (nm == "") { if (bandname != "") { nm = bandname; } else if (s.nlyr > 1) { nm = s.source_name + "_" + std::to_string(i+1); } else { nm = basename_noext(fname) ; } } std::string dtype = GDALGetDataTypeName(poBand->GetRasterDataType()); if ((!s.has_scale_offset[i]) && (in_string(dtype, "Int") || (dtype == "Byte"))) { s.valueType[i] = 1; } s.names[i] = nm; } if ((gdrv=="netCDF") || (gdrv == "HDF5")) { std::vector metadata; char **m = poDataset->GetMetadata(); while (*m != nullptr) { metadata.push_back(*m++); } std::string msg; s.set_names_time_ncdf(metadata, bandmeta, msg); if (msg.size() > 1) { addWarning(msg); } } GDALClose( (GDALDatasetH) poDataset ); s.hasValues = true; setSource(s); if (getCols) { setRGB(rgb_lyrs[0], rgb_lyrs[1], rgb_lyrs[2], -99, "rgb"); } return true; } bool SpatRaster::readStartGDAL(unsigned src) { GDALDataset *poDataset = openGDAL(source[src].filename, GDAL_OF_RASTER | GDAL_OF_READONLY, source[src].open_ops); if( poDataset == NULL ) { setError("cannot read from " + source[src].filename ); return false; } source[src].gdalconnection = poDataset; source[src].open_read = true; return(true); } bool SpatRaster::readStopGDAL(unsigned src) { if (source[src].gdalconnection != NULL) { GDALClose( (GDALDatasetH) source[src].gdalconnection); } source[src].open_read = false; return true; } void NAso(std::vector &d, size_t n, const std::vector &flags, const std::vector &scale, const std::vector &offset, const std::vector &haveso, const bool haveUserNAflag, const double userNAflag){ size_t nl = flags.size(); double na = NAN; for (size_t i=0; i &v, const size_t &ncell, const size_t &nrows, const size_t &ncols, const size_t &nl) { for (size_t i=0; i r(v.begin()+d1, v.begin()+d1+ncols); std::copy(v.begin()+d2, v.begin()+d2+ncols, v.begin()+d1); std::copy(r.begin(), r.end(), v.begin()+d2); } } } void SpatRaster::readChunkGDAL(std::vector &data, unsigned src, size_t row, unsigned nrows, size_t col, unsigned ncols) { if (source[src].multidim) { readValuesMulti(data, src, row, nrows, col, ncols); return; } if (source[src].hasWindow) { // ignoring the expanded case. row = row + source[src].window.off_row; col = col + source[src].window.off_col; } std::vector errout; if (source[src].rotated) { setError("cannot read from rotated files. First use 'rectify'"); return; } if (!source[src].open_read) { setError("the file is not open for reading"); return; } unsigned ncell = ncols * nrows; unsigned nl = source[src].nlyr; std::vector out(ncell * nl); int hasNA; std::vector naflags(nl, NAN); CPLErr err = CE_None; std::vector panBandMap; if (!source[src].in_order()) { panBandMap.reserve(nl); for (size_t i=0; i < nl; i++) { panBandMap.push_back(source[src].layers[i]+1); } } if (panBandMap.size() > 0) { err = source[src].gdalconnection->RasterIO(GF_Read, col, row, ncols, nrows, &out[0], ncols, nrows, GDT_Float64, nl, &panBandMap[0], 0, 0, 0, NULL); } else { err = source[src].gdalconnection->RasterIO(GF_Read, col, row, ncols, nrows, &out[0], ncols, nrows, GDT_Float64, nl, NULL, 0, 0, 0, NULL); } GDALRasterBand *poBand; if (err == CE_None ) { for (size_t i=0; iGetRasterBand(source[src].layers[i]+1); double naflag = poBand->GetNoDataValue(&hasNA); if (hasNA) naflags[i] = naflag; } NAso(out, ncell, naflags, source[src].scale, source[src].offset, source[src].has_scale_offset, source[src].hasNAflag, source[src].NAflag); } /* for (size_t i=0; i < nl; i++) { cell = ncell * i; poBand = source[src].gdalconnection->GetRasterBand(source[src].layers[i] + 1); double naflag = poBand->GetNoDataValue(&hasNA); if (!hasNA) { naflag = NAN; } GDALDataType gdtype = poBand->GetRasterDataType(); if (gdtype == GDT_Float64) { err = poBand->RasterIO(GF_Read, col, row, ncols, nrows, &out[cell], ncols, nrows, gdtype, 0, 0); if (err != CE_None ) { break; } set_NA(out, naflag); } } */ if (err != CE_None ) { setError("cannot read values"); return; } if (source[src].flipped) { vflip(out, ncell, nrows, ncols, nl); } data.insert(data.end(), out.begin(), out.end()); } std::vector SpatRaster::readValuesGDAL(unsigned src, size_t row, size_t nrows, size_t col, size_t ncols, int lyr) { std::vector errout; if (source[src].rotated) { setError("cannot read from rotated files. First use 'rectify'"); return errout; } if (source[src].hasWindow) { // ignoring the expanded case. row = row + source[src].window.off_row; col = col + source[src].window.off_col; } GDALDataset *poDataset = openGDAL(source[src].filename, GDAL_OF_RASTER | GDAL_OF_READONLY, source[src].open_ops); GDALRasterBand *poBand; if( poDataset == NULL ) { setError("cannot read values. Does the file still exist?"); return errout; } unsigned ncell = ncols * nrows; unsigned nl; std::vector panBandMap; if (lyr < 0) { nl = source[src].nlyr; if (!source[src].in_order()) { panBandMap.reserve(nl); for (size_t i=0; i < nl; i++) { panBandMap.push_back(source[src].layers[i]+1); } } } else { nl = 1; panBandMap.push_back(lyr+1); } std::vector out(ncell*nl); int hasNA; std::vector naflags(nl, NAN); CPLErr err = CE_None; if (panBandMap.size() > 0) { err = poDataset->RasterIO(GF_Read, col, row, ncols, nrows, &out[0], ncols, nrows, GDT_Float64, nl, &panBandMap[0], 0, 0, 0, NULL); } else { err = poDataset->RasterIO(GF_Read, col, row, ncols, nrows, &out[0], ncols, nrows, GDT_Float64, nl, NULL, 0, 0, 0, NULL); } if (err == CE_None ) { for (size_t i=0; iGetRasterBand(source[src].layers[i]+1); double naf = poBand->GetNoDataValue(&hasNA); if (hasNA) naflags[i] = naf; } NAso(out, ncell, naflags, source[src].scale, source[src].offset, source[src].has_scale_offset, source[src].hasNAflag, source[src].NAflag); } GDALClose((GDALDatasetH) poDataset); if (err != CE_None ) { setError("cannot read values"); return errout; } if (source[src].flipped) { vflip(out, ncell, nrows, ncols, nl); } return out; } std::vector SpatRaster::readGDALsample(unsigned src, size_t srows, size_t scols) { std::vector errout; if (source[src].rotated) { setError("cannot read from rotated files. First use 'rectify'"); return errout; } size_t row =0, col=0, nrows=nrow(), ncols=ncol(); if (source[src].hasWindow) { row = row + source[0].window.off_row; col = col + source[0].window.off_col; srows = std::min(srows, nrows); scols = std::min(scols, ncols); } GDALDataset *poDataset = openGDAL(source[src].filename, GDAL_OF_RASTER | GDAL_OF_READONLY, source[src].open_ops); if( poDataset == NULL ) { setError("no data"); return errout; } unsigned ncell = scols * srows; unsigned nl = source[src].nlyr; std::vector out(ncell*nl); int hasNA; CPLErr err = CE_None; std::vector naflags(nl, NAN); std::vector panBandMap; if (!source[src].in_order()) { panBandMap.reserve(nl); for (size_t i=0; i < nl; i++) { panBandMap.push_back(source[src].layers[i]+1); } } /* if (panBandMap.size() > 0) { err = poDataset->RasterIO(GF_Read, col, row, ncols, nrows, &out[0], scols, srows, GDT_Float64, nl, &panBandMap[0], 0, 0, 0, NULL); } else { err = poDataset->RasterIO(GF_Read, col, row, ncols, nrows, &out[0], scols, srows, GDT_Float64, nl, NULL, 0, 0, 0, NULL); } */ if (panBandMap.size() > 0) { err = poDataset->RasterIO(GF_Read, col, row, ncols, nrows, &out[0], scols, srows, GDT_Float64, nl, &panBandMap[0], 0, 0, 0, NULL); } else { err = poDataset->RasterIO(GF_Read, col, row, ncols, nrows, &out[0], scols, srows, GDT_Float64, nl, NULL, 0, 0, 0, NULL); } if (err == CE_None ) { GDALRasterBand *poBand; for (size_t i=0; iGetRasterBand(source[src].layers[i]+1); double naflag = poBand->GetNoDataValue(&hasNA); if (hasNA) naflags[i] = naflag; } NAso(out, ncell, naflags, source[src].scale, source[src].offset, source[src].has_scale_offset, source[src].hasNAflag, source[src].NAflag); } /* for (size_t i=0; i < nl; i++) { poBand = poDataset->GetRasterBand(source[src].layers[i] + 1); size_t off = i * ncell; err = poBand->RasterIO(GF_Read, 0, 0, ncol(), nrow(), &out[off], scols, srows, GDT_Float64, 0, 0); if (err != CE_None ) { break; } double naflag = poBand->GetNoDataValue(&hasNA); if (!hasNA) { naflag = NAN; } setNAso(out, off, ncell, naflag, source[src].scale[i], source[src].offset[i], source[src].has_scale_offset[i]); } */ GDALClose((GDALDatasetH) poDataset); if (err != CE_None ) { setError("cannot read values"); return errout; } if (source[src].flipped) { vflip(out, ncell, srows, scols, nl); } return out; } std::vector> SpatRaster::readRowColGDAL(unsigned src, std::vector &rows, const std::vector &cols) { std::vector> errout; if (source[src].rotated) { setError("cannot read from rotated files. First use 'rectify'"); return errout; } GDALDataset *poDataset = openGDAL(source[src].filename, GDAL_OF_RASTER | GDAL_OF_READONLY, source[src].open_ops); GDALRasterBand *poBand; if( poDataset == NULL ) { return errout; } std::vector lyrs = source[src].layers; unsigned nl = lyrs.size(); unsigned n = rows.size(); size_t fnr = nrow() - 1; if (source[src].flipped) { for (size_t i=0; i panBandMap; if (!source[src].in_order()) { panBandMap.reserve(nl); for (size_t i=0; i < nl; i++) { panBandMap.push_back(lyrs[i]+1); } } std::vector out(n * nl, NAN); CPLErr err = CE_None; for (size_t j=0; j < n; j++) { if ((cols[j] < 0) || (rows[j] < 0)) continue; if (panBandMap.size() > 0) { err = poDataset->RasterIO(GF_Read, cols[j], rows[j], 1, 1, &out[j*nl], 1, 1, GDT_Float64, nl, &panBandMap[0], 0, 0, 0, NULL); } else { err = poDataset->RasterIO(GF_Read, cols[j], rows[j], 1, 1, &out[j*nl], 1, 1, GDT_Float64, nl, NULL, 0, 0, 0, NULL); } if (err != CE_None ) { break; } } if (err == CE_None ) { std::vector naflags(nl, NAN); int hasNA; for (size_t i=0; iGetRasterBand(lyrs[i]+1); double naflag = poBand->GetNoDataValue(&hasNA); if (hasNA) naflags[i] = naflag; } NAso(out, n, naflags, source[src].scale, source[src].offset, source[src].has_scale_offset, source[src].hasNAflag, source[src].NAflag); } GDALClose((GDALDatasetH) poDataset); if (err != CE_None ) { setError("cannot read values"); return errout; } size_t nr = rows.size(); std::vector> r(nl, std::vector (nr)); for (size_t i=0; i SpatRaster::readRowColGDALFlat(unsigned src, std::vector &rows, const std::vector &cols) { std::vector errout; if (source[src].rotated) { setError("cannot read from rotated files. First use 'rectify'"); return errout; } GDALDataset *poDataset = openGDAL(source[src].filename, GDAL_OF_RASTER | GDAL_OF_READONLY, source[src].open_ops); GDALRasterBand *poBand; if( poDataset == NULL ) { return errout; } std::vector lyrs = source[src].layers; unsigned nl = lyrs.size(); unsigned n = rows.size(); size_t fnr = nrow() - 1; if (source[src].flipped) { for (size_t i=0; i panBandMap; if (!source[src].in_order()) { panBandMap.reserve(nl); for (size_t i=0; i < nl; i++) { panBandMap.push_back(lyrs[i]+1); } } std::vector out(n * nl, NAN); CPLErr err = CE_None; for (size_t j=0; j < n; j++) { if ((cols[j] < 0) || (rows[j] < 0)) continue; if (panBandMap.size() > 0) { err = poDataset->RasterIO(GF_Read, cols[j], rows[j], 1, 1, &out[j*nl], 1, 1, GDT_Float64, nl, &panBandMap[0], 0, 0, 0, NULL); } else { err = poDataset->RasterIO(GF_Read, cols[j], rows[j], 1, 1, &out[j*nl], 1, 1, GDT_Float64, nl, NULL, 0, 0, 0, NULL); } if (err != CE_None ) { break; } } if (err == CE_None ) { std::vector naflags(nl, NAN); int hasNA; for (size_t i=0; iGetRasterBand(lyrs[i]+1); double naflag = poBand->GetNoDataValue(&hasNA); if (hasNA) naflags[i] = naflag; } NAso(out, n, naflags, source[src].scale, source[src].offset, source[src].has_scale_offset, source[src].hasNAflag, source[src].NAflag); } GDALClose((GDALDatasetH) poDataset); if (err != CE_None ) { setError("cannot read values"); return errout; } return out; } // ncdf bool ncdf_good_ends(std::string const &s) { std::vector end = {"_bnds", "_bounds", "lat", "lon", "longitude", "latitude"}; for (size_t i=0; i= end[i].length()) { if (s.compare(s.length() - end[i].length(), s.length(), end[i]) == 0) { return false; } } } if (s == "x" || s == "y" || s == "northing" || s == "easting") { return false; } return true; } void ncdf_pick_most(std::vector &sd, std::vector &varname, std::vector &longname, std::vector &dim1, std::vector &dim2) { if (sd.size() < 2) return; std::vector ud = dim1; std::sort(ud.begin(), ud.end()); ud.erase(std::unique(ud.begin(), ud.end()), ud.end()); if (ud.size() > 1) { std::vector tmpsd, tmpvarname, tmplongname; std::vector tmpdim1, tmpdim2; int mx = ud[ud.size()-1]; for (size_t i=0; i meta, std::vector subds, std::vector subdsname, std::vector options, bool ncdf) { std::vector> info = parse_metadata_sds(meta); int n = info[0].size(); std::vector sd, varname, srcname; // std::vector varnl; // for selection based on nlyr if (info[0].size() == 0) { return false; } // select sds by index if ((subds.size() > 0) && (subds[0] >= 0)) { for (size_t i=0; i=0 && subds[i] < n) { sd.push_back(info[0][subds[i]]); varname.push_back(info[1][i]); } else { std::string emsg = std::to_string(subds[i]+1) + " is not valid. There are " + std::to_string(info[0].size()) + " subdatasets\n"; setError(emsg); return false; } } // select by name } else if ((subdsname.size() > 0) && (subdsname[0] != "")) { for (size_t i=0; i= 0) { sd.push_back(info[0][w]); varname.push_back(info[1][w]); } else { std::string emsg = concatenate(info[1], ", "); emsg = subdsname[i] + " not found. Choose one of:\n" + emsg; setError(emsg); return false; } } // select all } else { // eliminate sources based on names like "*_bnds" and "lat" std::vector rows, cols; for (size_t i=0; i nl(n); for (size_t i=0; i srcnl; size_t cnt; for (cnt=0; cnt < sd.size(); cnt++) { if (constructFromFile(sd[cnt], {-1}, {""}, options)) break; } // source[0].source_name = srcname[cnt]; std::vector skipped, used; srcnl.push_back(nlyr()); used.push_back(varname[0]); SpatRaster out; SpatOptions opt; for (size_t i=(cnt+1); i < sd.size(); i++) { // printf( "%s\n", sd[i].c_str() ); bool success = out.constructFromFile(sd[i], {-1}, {""}, {}); if (success) { if (out.compare_geom(*this, false, false, 0.1)) { // out.source [0].source_name = srcname[i]; addSource(out, false, opt); srcnl.push_back(out.nlyr()); used.push_back(varname[i]); } else { skipped.push_back(varname[i]); } } else { skipped.push_back(varname[i]); } } if (skipped.size() > 0) { std::string s="skipped sub-datasets (see 'desc(sds=TRUE)'):\n" + skipped[0]; for (size_t i=1; i lyrnames; for (size_t i=0; i nms = { basename(used[i]) }; recycle(nms, srcnl[i]); make_unique_names(nms); lyrnames.insert(lyrnames.end(), nms.begin(), nms.end()); } if (lyrnames.size() > 0) { setNames(lyrnames, false); } } return true; } std::vector ncdf_str2int64v(std::string s, std::string delim) { std::vector out; size_t pos = 0; while ((pos = s.find(delim)) != std::string::npos) { std::string v = s.substr(0, pos); s.erase(0, pos + 1); out.push_back(std::stoll(v)); } out.push_back(std::stoll(s)); return out; } bool get_long(std::string input, long &output) { try { output = std::stoi(input); return true; } catch (std::invalid_argument &e) { return false; } } bool get_double(std::string input, double &output) { try { output = std::stod(input); return true; } catch (std::invalid_argument &e) { return false; } } std::vector ncdf_time(const std::vector &metadata, std::vector vals, std::string &step, std::string &msg) { std::vector out, bad; if (vals.size() < 1) { step = ""; return out; } std::vector raw; raw.reserve(vals.size()); for (size_t i=0; i ymd = getymd(origin); if (calendar == "noleap" || calendar == "365_day" || calendar == "365 day") { for (size_t i=0; i ymd = getymd(origin); for (size_t i=0; i> ncdf_names(const std::vector> &m) { std::vector> out(3); if (m.size() < 1) return out; std::string vname, lname, units = ""; std::vector b = m[0]; for (size_t j=0; j metadata, std::vector> bandmeta, std::string &msg) { if (bandmeta.size() == 0) return; std::vector> nms = ncdf_names(bandmeta); if (nms[1].size() > 0) { names = nms[1]; make_unique_names(names); } source_name = nms[2][0]; source_name_long = nms[2][1]; if (nms[2][2].size() == 0) { unit = {""}; } else { unit = {nms[2][2]}; } recycle(unit, nlyr); if (nms[0].size() > 0) { std::string step; std::vector x = ncdf_time(metadata, nms[0], step, msg); if (x.size() == nlyr) { time = x; timestep = step; hasTime = true; } } } terra/src/spatSources.cpp0000644000175000017500000003557214201035750015340 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include #include "spatRaster.h" /* #include "string_utils.h" void SpatRasterSource::fsopen(std::string filename) { std::string grifile = setFileExt(filename, ".gri"); std::ofstream fstr(grifile, std::ios::out | std::ios::binary); *ofs = &fstr; } bool SpatRasterSource::fswrite(std::vector &v) { unsigned sz = v.size() * sizeof(double); bool result = (*ofs).write(reinterpret_cast(&v[0]), sz); return result; } void SpatRasterSource::fsclose() { (*ofs).close(); } */ SpatRasterSource::SpatRasterSource() { open_write = false; open_read = false; } SpatRaster SpatRaster::combineSources(SpatRaster x, bool warn) { SpatRaster out = geometry(); if (!hasValues()) { if (!x.hasValues()) { if (out.compare_geom(x, false, false, 0.1)) { out.source.insert(out.source.end(), x.source.begin(), x.source.end()); out.setNames(out.getNames()); } else { out = x.deepCopy(); if (warn) { out.addWarning("both rasters were empty, but had different geometries. The first one was ignored"); } } } else { out = x.deepCopy(); if (warn) { out.addWarning("the first raster was empty and ignored"); } } return out; } if (!out.compare_geom(x, false, false, 0.1)) { return out; } out = deepCopy(); if (!x.hasValues()) { out.addWarning("you cannot add SpatRaster with no values to one that has values"); return(out); } out.source.insert(out.source.end(), x.source.begin(), x.source.end()); // to make names unique (not great of called several times //out.setNames(out.getNames()); return(out); } void SpatRaster::combine(SpatRaster x) { if (!compare_geom(x, false, false, 0.1)) { return; } bool hv = hasValues(); if (hv != x.hasValues()) { setError("combined sources must all have values; or none should have values"); return; } source.insert(source.end(), x.source.begin(), x.source.end()); //setNames(getNames()); return; } void SpatRaster::addSource(SpatRaster x, bool warn, SpatOptions &opt) { if (!hasValues()) { if (!x.hasValues()) { if (compare_geom(x, false, false, 0.1)) { source.insert(source.end(), x.source.begin(), x.source.end()); } else { source = x.source; if (warn) { addWarning("both rasters were empty, but had different geometries. The first one was ignored"); } } } else { source = x.source; if (warn) { addWarning("the first raster was empty and ignored"); } } return; } if (!x.hasValues()) { x = x.init({NAN}, opt); } if (compare_geom(x, false, false, 0.1)) { source.insert(source.end(), x.source.begin(), x.source.end()); } } unsigned SpatRaster::nsrc() { return source.size(); } int SpatRaster::sourceFromLyr(unsigned lyr) { if (lyr >= nlyr()) { return(-1); } unsigned nsrc = 0; unsigned nlyrs = -1; for (size_t i=0; i= lyr) break; nsrc++; } return nsrc; } std::vector SpatRaster::nlyrBySource() { std::vector lyrs(source.size()); for (size_t i=0; i SpatRaster::lyrsBySource() { std::vector lyrs(nlyr()); unsigned start = 0; for (size_t i=0; i SpatRaster::findLyr(unsigned lyr) { std::vector sl(2); unsigned nlyrs = 0; unsigned start = 0; bool done = false; for (size_t i=0; i= lyr) { sl[0] = i; for (size_t j=start; j SpatRaster::getBands() { std::vector out; for (size_t i=0; i SpatRaster::sourcesFromLyrs(std::vector lyrs) { std::vector s(lyrs.size()); std::vector slyrs = lyrsBySource(); for (size_t i=0; i &v, unsigned lyr) { size_t nc ; if (hasWindow) { nc = window.full_ncol * window.full_nrow; } else { nc = nrow * ncol; } size_t start = lyr * nc; v = std::vector(values.begin()+start, values.begin()+start+nc); } */ void SpatRasterSource::appendValues(std::vector &v, unsigned lyr) { size_t nc ; if (hasWindow) { nc = window.full_ncol * window.full_nrow; } else { nc = nrow * ncol; } size_t start = lyr * nc; v.insert(v.end(), values.begin()+start, values.begin()+start+nc); } bool SpatRasterSource::in_order() { if (memory) return true; if (nlyr != nlyrfile) return false; for (size_t i=0; i SpatRasterSource::subset(std::vector lyrs) { SpatRasterSource SpatRasterSource::subset(std::vector lyrs) { unsigned nl = lyrs.size(); bool all = true; if (lyrs.size() == nlyr) { for (size_t i=0; i validLayers( std::vector lyrs , unsigned nl) { unsigned s = lyrs.size(); for (size_t i=0; i= nl) { lyrs.erase(lyrs.begin() + j); } } /* or unsigned s = lyrs.size() - 1; for (long i=s; i>=0; i--) { if ((lyrs[i] < 0) | (lyrs[i] >= nl)) { lyrs.erase(lyrs.begin() + i); } } */ return lyrs; } SpatRaster SpatRaster::subset(std::vector lyrs, SpatOptions &opt) { SpatRaster out = geometry(1); out.source.resize(0); unsigned oldsize = lyrs.size(); lyrs = validLayers(lyrs, nlyr()); if (lyrs.size() == 0) { out.setError("no (valid) layer references"); return(out); } else if (lyrs.size() != oldsize) { out.addWarning("ignored " + std::to_string(oldsize - lyrs.size()) + " invalid layer reference(s)"); } std::vector srcs = sourcesFromLyrs(lyrs); unsigned ss = srcs[0]; std::vector slyr; std::vector lyrbys = nlyrBySource(); // SpatRasterSource rs; unsigned offset = 0; for (size_t i=0; i rem; for (size_t i=1; i= 0; i--) { source.erase(source.begin()+i); } } SpatRaster SpatRaster::collapse_sources() { SpatRaster out; std::vector src; SpatRasterSource s = source[0]; for (size_t i=1; i. #include "spatVector.h" #include "file_utils.h" #include "ogrsf_frmts.h" #include "ogr_spatialref.h" #include "crs.h" #include "string_utils.h" std::string geomType(OGRLayer *poLayer) { std::string s = ""; poLayer->ResetReading(); OGRFeature *poFeature; while( (poFeature = poLayer->GetNextFeature()) != NULL ) { OGRGeometry *poGeometry = poFeature->GetGeometryRef(); const char* gname = poGeometry->getGeometryName(); s = gname; break; } OGRFeature::DestroyFeature( poFeature ); return s; } SpatDataFrame readAttributes(OGRLayer *poLayer, bool as_proxy) { SpatDataFrame df; OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn(); size_t nfields = poFDefn->GetFieldCount(); if (nfields == 0) return df; OGRFieldType ft; poLayer->ResetReading(); OGRFeature *poFeature; OGRFieldDefn *poFieldDefn; df.resize_cols(nfields); bool first = true; unsigned dtype; while( (poFeature = poLayer->GetNextFeature()) != NULL ) { if (first) { for (size_t i = 0; i < nfields; i++ ) { poFieldDefn = poFDefn->GetFieldDefn(i); std::string fname = poFieldDefn->GetNameRef(); ft = poFieldDefn->GetType(); if (ft == OFTReal) { dtype = 0; } else if ((ft == OFTInteger) | (ft == OFTInteger64)) { dtype = 1; } else { dtype = 2; } df.add_column(dtype, fname); } first = false; } for (size_t i = 0; i < nfields; i++ ) { poFieldDefn = poFDefn->GetFieldDefn( i ); unsigned j = df.iplace[i]; switch( poFieldDefn->GetType() ) { case OFTReal: df.dv[j].push_back(poFeature->GetFieldAsDouble(i)); break; case OFTInteger: df.iv[j].push_back(poFeature->GetFieldAsInteger( i )); break; case OFTInteger64: df.iv[j].push_back(poFeature->GetFieldAsInteger64( i )); break; // case OFTString: default: df.sv[j].push_back(poFeature->GetFieldAsString( i )); break; } } OGRFeature::DestroyFeature( poFeature ); if (as_proxy) break; } return df; } /* std::string getDs_WKT(GDALDataset *poDataset) { std::string wkt = ""; char *cp; #if GDAL_VERSION_MAJOR >= 3 const OGRSpatialReference *srs = poDataset->GetSpatialRef(); const char *options[3] = { "MULTILINE=YES", "FORMAT=WKT2", NULL }; OGRErr err = srs->exportToWkt(&cp, options); if (err == OGRERR_NONE) { wkt = std::string(cp); CPLFree(cp); } #else const char *pszSrc = GDALGetProjectionRef( poDataset ); if (pszSrc != NULL) { wkt = std::string(pszSrc); } // if (poDataset->GetProjectionRef() != NULL) { // OGRSpatialReference oSRS(poDataset->GetProjectionRef()); // OGRErr err = oSRS.exportToPrettyWkt(&cp); // if (err == OGRERR_NONE) { // wkt = std::string(cp); // CPLFree(cp); // } // } #endif return wkt; } std::string getDs_PRJ(GDALDataset *poDataset) { std::string prj = ""; #if GDAL_VERSION_MAJOR >= 3 char *cp; const OGRSpatialReference *srs = poDataset->GetSpatialRef(); OGRErr err = srs->exportToProj4(&cp); if (err == OGRERR_NONE) { prj = std::string(cp); CPLFree(cp); } #else if( poDataset->GetProjectionRef() != NULL ) { OGRSpatialReference oSRS(poDataset->GetProjectionRef()); char *pszPRJ = NULL; oSRS.exportToProj4(&pszPRJ); prj = pszPRJ; } #endif return prj; } */ SpatGeom getPointGeom(OGRGeometry *poGeometry) { SpatGeom g(points); if (poGeometry->IsEmpty()) { return g; } #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0) OGRPoint *poPoint = poGeometry->toPoint(); #else OGRPoint *poPoint = (OGRPoint *) poGeometry; #endif double x = poPoint->getX(); double y = poPoint->getY(); SpatPart p(x, y); g.addPart(p); return g; } SpatGeom getMultiPointGeom(OGRGeometry *poGeometry) { OGRMultiPoint *poMultipoint = ( OGRMultiPoint * )poGeometry; unsigned ng = poMultipoint->getNumGeometries(); std::vector X(ng); std::vector Y(ng); for (size_t i=0; igetGeometryRef(i); #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0) OGRPoint *poPoint = poMpGeometry->toPoint(); #else OGRPoint *poPoint = (OGRPoint *) poMpGeometry; #endif X[i] = poPoint->getX(); Y[i] = poPoint->getY(); } SpatPart p(X, Y); SpatGeom g(points); g.addPart(p); return g; } SpatGeom getLinesGeom(OGRGeometry *poGeometry) { OGRLineString *poGeom = (OGRLineString *) poGeometry; unsigned np = poGeom->getNumPoints(); std::vector X(np); std::vector Y(np); OGRPoint ogrPt; for (size_t i=0; igetPoint(i, &ogrPt); X[i] = ogrPt.getX(); Y[i] = ogrPt.getY(); } SpatPart p(X, Y); SpatGeom g(lines); g.addPart(p); return g; } SpatGeom getMultiLinesGeom(OGRGeometry *poGeometry) { SpatGeom g(lines); OGRMultiLineString *poGeom = ( OGRMultiLineString * )poGeometry; unsigned ng = poGeom->getNumGeometries(); OGRPoint ogrPt; for (size_t i=0; igetGeometryRef(i); OGRLineString *poLine = ( OGRLineString * )poLineGeometry; unsigned np = poLine->getNumPoints(); std::vector X(np); std::vector Y(np); for (size_t j=0; jgetPoint(j, &ogrPt); X[j] = ogrPt.getX(); Y[j] = ogrPt.getY(); } SpatPart p(X, Y); g.addPart(p); } return g; } //#include "Rcpp.h" SpatGeom getPolygonsGeom(OGRGeometry *poGeometry) { SpatGeom g(polygons); OGRPoint ogrPt; // OGRwkbGeometryType geomtype = poGeometry->getGeometryType(); // if ( geomtype == wkbPolygon ) { OGRPolygon *poGeom = ( OGRPolygon * )poGeometry; OGRLinearRing *poRing = poGeom->getExteriorRing(); unsigned np = poRing->getNumPoints(); std::vector X(np); std::vector Y(np); for (size_t i=0; igetPoint(i, &ogrPt); X[i] = ogrPt.getX(); Y[i] = ogrPt.getY(); } SpatPart p(X, Y); unsigned nh = poGeom->getNumInteriorRings(); for (size_t i=0; igetInteriorRing(i); unsigned np = poHole->getNumPoints(); std::vector X(np); std::vector Y(np); for (size_t j=0; jgetPoint(j, &ogrPt); X[j] = ogrPt.getX(); Y[j] = ogrPt.getY(); } p.addHole(X, Y); } g.addPart(p); // } return g; } SpatGeom getMultiPolygonsGeom(OGRGeometry *poGeometry) { OGRMultiPolygon *poGeom = ( OGRMultiPolygon * )poGeometry; OGRPoint ogrPt; unsigned ng = poGeom->getNumGeometries(); SpatGeom g(polygons); for (size_t i=0; igetGeometryRef(i); OGRPolygon *poPolygon = ( OGRPolygon * )poPolygonGeometry; OGRLinearRing *poRing = poPolygon->getExteriorRing(); unsigned np = poRing->getNumPoints(); std::vector X(np); std::vector Y(np); for (size_t j=0; jgetPoint(j, &ogrPt); X[j] = ogrPt.getX(); Y[j] = ogrPt.getY(); } SpatPart p(X, Y); unsigned nh = poPolygon->getNumInteriorRings(); for (size_t j=0; jgetInteriorRing(j); np = poHole->getNumPoints(); std::vector X(np); std::vector Y(np); for (size_t k = 0; k < np; k++ ) { poHole->getPoint(k, &ogrPt); X[k] = ogrPt.getX(); Y[k] = ogrPt.getY(); } p.addHole(X, Y); } g.addPart(p); } return g; } std::vector SpatVector::layer_names(std::string filename) { std::vector out; if (filename == "") { setError("empty filename"); return out; } if (!file_exists(filename)) { setError("file does not exist"); return out; } GDALDataset *poDS = static_cast(GDALOpenEx(filename.c_str(), GDAL_OF_VECTOR, NULL, NULL, NULL )); if( poDS == NULL ) { setError("Cannot open this dataset" ); return out; } size_t n = poDS->GetLayerCount(); out.reserve(n); for (size_t i=0; iGetLayer(i); if (poLayer == NULL) { out.push_back(""); } else { out.push_back((std::string)poLayer->GetName()); } } GDALClose(poDS); return out; } bool SpatVector::read_ogr(GDALDataset *poDS, std::string layer, std::string query, std::vector extent, SpatVector filter, bool as_proxy) { std::string crs = ""; OGRSpatialReference *poSRS = poDS->GetLayer(0)->GetSpatialRef(); if (poSRS) { char *psz = NULL; OGRErr err = poSRS->exportToWkt(&psz); if (err == OGRERR_NONE) { crs = psz; } setSRS(crs); CPLFree(psz); } OGRLayer *poLayer; if (query != "") { poLayer = poDS->ExecuteSQL(query.c_str(), NULL, NULL); if (poLayer == NULL) { setError("Query failed"); return false; } read_query = query; } else { if (layer == "") { #if GDAL_VERSION_MAJOR <= 2 && GDAL_VERSION_MINOR <= 2 // do nothing #else std::vector lyrnms; for ( auto&& poLayer: poDS->GetLayers() ) { lyrnms.push_back((std::string)poLayer->GetName()); } if (lyrnms.size() > 1) { std::string lyrsel = lyrnms[0]; lyrnms.erase(lyrnms.begin()); std::string ccat = concatenate(lyrnms, ", "); std::string msg = "Reading layer: " + lyrsel + "\nOther layers: " + ccat; addWarning(msg); } #endif poLayer = poDS->GetLayer(0); if (poLayer == NULL) { setError("dataset has no layers"); return false; } } else { poLayer = poDS->GetLayerByName(layer.c_str()); if (poLayer == NULL) { std::string msg = layer + " is not a valid layer name"; #if GDAL_VERSION_MAJOR <= 2 && GDAL_VERSION_MINOR <= 2 // do nothing #else msg += "\nChoose one of: "; for ( auto&& poLayer: poDS->GetLayers() ) { msg += (std::string)poLayer->GetName() + ", "; } msg = msg.substr(0, msg.size()-2); #endif setError(msg); return false; } } } if (filter.nrow() > 0) { if (filter.type() != "polygons") { filter = filter.hull("convex"); } else { if (filter.nrow() > 1) { filter = filter.aggregate(true); } } GDALDataset *filterDS = filter.write_ogr("", "lyr", "Memory", false, true, std::vector()); if (filter.hasError()) { setError(filter.getError()); GDALClose(filterDS); return false; } OGRLayer *fLayer = filterDS->GetLayer(0); fLayer->ResetReading(); OGRFeature *fFeature = fLayer->GetNextFeature(); if (fFeature != NULL ) { OGRGeometry *fGeometry = fFeature->StealGeometry(); poLayer->SetSpatialFilter(fGeometry); OGRGeometryFactory::destroyGeometry(fGeometry); } OGRFeature::DestroyFeature( fFeature ); GDALClose(filterDS); } else if (extent.size() > 0) { poLayer->SetSpatialFilterRect(extent[0], extent[2], extent[1], extent[3]); read_extent = extent; } //const char* lname = poLayer->GetName(); OGRwkbGeometryType wkbgeom = wkbFlatten(poLayer->GetGeomType()); df = readAttributes(poLayer, as_proxy); OGRFeature *poFeature; poLayer->ResetReading(); poFeature = poLayer->GetNextFeature(); if (poFeature != NULL) { OGRGeometry *poGeometry = poFeature->GetGeometryRef(); if (poGeometry != NULL) { if (poGeometry->Is3D()) { addWarning("Z coordinates ignored"); } if (poGeometry->IsMeasured()) { addWarning("M coordinates ignored"); } } } source_layer = poLayer->GetName(); if (as_proxy) { SpatGeom g; if ((wkbgeom == wkbPoint) | (wkbgeom == wkbMultiPoint)) { //SpatPart p(0,0); OGRGeometry *poGeometry = poFeature->GetGeometryRef(); if (poGeometry != NULL) { if ( wkbFlatten(poGeometry->getGeometryType()) == wkbPoint ) { g = getPointGeom(poGeometry); } else { g = getMultiPointGeom(poGeometry); } } else { SpatPart p; g = SpatGeom(); g.addPart(p); } addGeom(g); OGRFeature::DestroyFeature( poFeature ); } else if (wkbgeom == wkbLineString || wkbgeom == wkbMultiLineString) { OGRGeometry *poGeometry = poFeature->GetGeometryRef(); if (poGeometry != NULL) { if (wkbFlatten ( poGeometry ->getGeometryType() ) == wkbLineString) { g = getLinesGeom(poGeometry); } else { g = getMultiLinesGeom(poGeometry); } } else { SpatPart p; g = SpatGeom(); g.addPart(p); } addGeom(g); OGRFeature::DestroyFeature( poFeature ); } else if ( wkbgeom == wkbPolygon || wkbgeom == wkbMultiPolygon) { OGRGeometry *poGeometry = poFeature->GetGeometryRef(); if (poGeometry != NULL) { wkbgeom = wkbFlatten(poGeometry->getGeometryType()); if (wkbgeom == wkbPolygon) { g = getPolygonsGeom(poGeometry); } else if (wkbgeom == wkbMultiPolygon ) { g = getMultiPolygonsGeom(poGeometry); } } else { g = SpatGeom(); } addGeom(g); OGRFeature::DestroyFeature( poFeature ); } else if (wkbgeom != wkbNone) { const char *geomtypechar = OGRGeometryTypeToName(wkbgeom); std::string strgeomtype = geomtypechar; std::string s = "cannot read this geometry type: "+ strgeomtype; setError(s); return false; } geom_count = poLayer->GetFeatureCount(); is_proxy = true; return true; } OGRFeature::DestroyFeature( poFeature ); poLayer->ResetReading(); SpatGeom g; if ((wkbgeom == wkbPoint) | (wkbgeom == wkbMultiPoint)) { //SpatPart p(0,0); while( (poFeature = poLayer->GetNextFeature()) != NULL ) { OGRGeometry *poGeometry = poFeature->GetGeometryRef(); if (poGeometry != NULL) { if ( wkbFlatten(poGeometry->getGeometryType()) == wkbPoint ) { g = getPointGeom(poGeometry); } else { g = getMultiPointGeom(poGeometry); } } else { SpatPart p; g = SpatGeom(); g.addPart(p); } addGeom(g); OGRFeature::DestroyFeature( poFeature ); } } else if (wkbgeom == wkbLineString || wkbgeom == wkbMultiLineString) { while ( (poFeature = poLayer->GetNextFeature()) != NULL ) { OGRGeometry *poGeometry = poFeature->GetGeometryRef(); if (poGeometry != NULL) { if (wkbFlatten ( poGeometry ->getGeometryType() ) == wkbLineString) { g = getLinesGeom(poGeometry); } else { g = getMultiLinesGeom(poGeometry); } } else { SpatPart p; g = SpatGeom(); g.addPart(p); } addGeom(g); OGRFeature::DestroyFeature( poFeature ); } } else if ( wkbgeom == wkbPolygon || wkbgeom == wkbMultiPolygon) { while ( (poFeature = poLayer->GetNextFeature()) != NULL ) { OGRGeometry *poGeometry = poFeature->GetGeometryRef(); if (poGeometry != NULL) { wkbgeom = wkbFlatten(poGeometry->getGeometryType()); if (wkbgeom == wkbPolygon) { g = getPolygonsGeom(poGeometry); } else if (wkbgeom == wkbMultiPolygon ) { g = getMultiPolygonsGeom(poGeometry); } } else { g = SpatGeom(); } addGeom(g); OGRFeature::DestroyFeature( poFeature ); } } else if (wkbgeom != wkbNone) { const char *geomtypechar = OGRGeometryTypeToName(wkbgeom); std::string strgeomtype = geomtypechar; std::string s = "cannot read this geometry type: "+ strgeomtype; setError(s); return false; } if (query != "") { poDS->ReleaseResultSet(poLayer); } return true; } bool SpatVector::read(std::string fname, std::string layer, std::string query, std::vector extent, SpatVector filter, bool as_proxy) { //OGRRegisterAll(); GDALDataset *poDS = static_cast(GDALOpenEx( fname.c_str(), GDAL_OF_VECTOR, NULL, NULL, NULL )); if( poDS == NULL ) { setError("Cannot open this file as a SpatVector"); return false; } bool success = read_ogr(poDS, layer, query, extent, filter, as_proxy); if (poDS != NULL) GDALClose( poDS ); source = fname; return success; } SpatVector SpatVector::fromDS(GDALDataset *poDS) { SpatVector out, fvct; std::vector fext; out.read_ogr(poDS, "", "", fext, fvct, false); return out; } SpatVector::SpatVector(std::vector wkt) { OGRGeometryFactory ogr; SpatGeom g; for (size_t i=0; i cstr = { cstring }; OGRErr err = ogr.createFromWkt(&cstr[0], NULL, &poGeometry ); #else const char* pszWKT = wkt[i].c_str(); OGRErr err = ogr.createFromWkt( pszWKT, NULL, &poGeometry ); #endif if (err == OGRERR_NONE) { //const char* gname = poGeometry->getGeometryName(); if (poGeometry != NULL) { OGRwkbGeometryType gtype = wkbFlatten(poGeometry->getGeometryType()); if ( gtype == wkbPoint ) { g = getPointGeom(poGeometry); } else if ( gtype == wkbMultiPoint ) { g = getMultiPointGeom(poGeometry); } else if (gtype == wkbLineString) { g = getLinesGeom(poGeometry); } else if (gtype == wkbMultiLineString) { g = getMultiLinesGeom(poGeometry); } else if (gtype == wkbPolygon) { g = getPolygonsGeom(poGeometry); } else if (gtype == wkbMultiPolygon ) { g = getMultiPolygonsGeom(poGeometry); } else { const char *geomtypechar = OGRGeometryTypeToName(gtype); std::string strgeomtype = geomtypechar; std::string s = "cannot read geometry type: "+ strgeomtype; setError(s); return; } addGeom(g); OGRGeometryFactory::destroyGeometry(poGeometry); } } else { setError("not WKT"); return; } } } terra/src/distance.h0000644000175000017500000001034414201035750014252 0ustar nileshnilesh// Copyright (c) 2018-2020 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . // distance double distance_plane(const double &x1, const double &y1, const double &x2, const double &y2); std::vector distance_plane(std::vector &x1, std::vector &y1, std::vector &x2, std::vector &y2); std::vector distance_plane_vd(std::vector &x1, std::vector &y1, double x2, double y2); double distance_haversine(double lon1, double lat1, double lon2, double lat2); double distance_lonlat(const double &lon1, const double &lat1, const double &lon2, const double &lat2); std::vector distance_lonlat(std::vector &lon1, std::vector &lat1, std::vector &lon2, std::vector &lat2) ; std::vector distance_lonlat_vd(std::vector &lon1, std::vector &lat1, double lon2, double lat2) ; double distHaversine(double lon1, double lat1, double lon2, double lat2); // direction double direction_lonlat(double lon1, double lat1, double lon2, double lat2, bool degrees); std::vector direction_lonlat(std::vector lon1, std::vector lat1, std::vector lon2, std::vector lat2, bool degrees); void directionToNearest_lonlat(std::vector &azi, const std::vector &lon1, const std::vector &lat1, const std::vector &lon2, const std::vector &lat2, bool °rees, bool &from); void distanceCosineToNearest_lonlat(std::vector &d, const std::vector &lon1, const std::vector &lat1, const std::vector &lon2, const std::vector &lat2); double direction_plane(double x1, double y1, double x2, double y2, bool degrees); std::vector direction_plane(std::vector x1, std::vector y1, std::vector x2, std::vector y2, bool degrees); void directionToNearest_plane(std::vector &r, const std::vector &x1, const std::vector &y1, const std::vector &x2, const std::vector &y2, bool °rees, bool &from); // destination std::vector destpoint_lonlat(double longitude, double latitude, double bearing, double distance); std::vector> destpoint_lonlat(const std::vector& longitude, const std::vector& latitude, const std::vector& bearing, const std::vector& distance); std::vector> destpoint_lonlat(const double& longitude, const double& latitude, const std::vector& bearing, const double& distance, bool wrap=true); std::vector destpoint_plane(double x, double y, double bearing, double distance); std::vector > destpoint_plane(std::vector x, std::vector y, std::vector bearing, std::vector distance); double toRad(double °); void distanceToNearest_plane(std::vector &d, const std::vector &x1, const std::vector &y1, const std::vector &x2, const std::vector &y2, const double& lindist); void distanceToNearest_lonlat(std::vector &d, const std::vector &lon1, const std::vector &lat1, const std::vector &lon2, const std::vector &lat2); void nearest_lonlat(std::vector &id, std::vector &d, std::vector &nlon, std::vector &nlat, const std::vector &lon1, const std::vector &lat1, const std::vector &lon2, const std::vector &lat2); void nearest_lonlat_self(std::vector &id, std::vector &d, std::vector &nlon, std::vector &nlat, const std::vector &lon, const std::vector &lat); terra/src/RcppModule.cpp0000644000175000017500000010760514202042425015072 0ustar nileshnilesh#include //#include "spatRaster.h" #include "spatRasterMultiple.h" #include //std::addressof //static void SpatRaster_finalizer( SpatRaster* ptr ){ //} Rcpp::List getBlockSizeR(SpatRaster* r, unsigned n, double frac) { SpatOptions opt; opt.ncopies = n; opt.set_memfrac(frac); BlockSize bs = r->getBlockSize(opt); Rcpp::List L = Rcpp::List::create(Rcpp::Named("row") = bs.row, Rcpp::Named("nrows") = bs.nrows, Rcpp::Named("n") = bs.n); return(L); } Rcpp::List getBlockSizeWrite(SpatRaster* r) { BlockSize bs = r->bs; Rcpp::List L = Rcpp::List::create(Rcpp::Named("row") = bs.row, Rcpp::Named("nrows") = bs.nrows, Rcpp::Named("n") = bs.n); return(L); } bool sameObject(SpatRaster* a, SpatRaster* b) { return a == b; } Rcpp::List getDataFrame(SpatDataFrame* v) { unsigned n = v->ncol(); Rcpp::List out(n); if (n == 0) { return(out); } std::vector nms = v->names; std::vector itype = v->itype; for (size_t i=0; i < n; i++) { if (itype[i] == 0) { out[i] = v->getD(i); } else if (itype[i] == 1) { Rcpp::NumericVector iv = Rcpp::wrap(v->getI(i)); for (R_xlen_t j=0; jgetS(i)); for (R_xlen_t j=0; jnames(); // return result; } Rcpp::List getVectorAttributes(SpatVector* v) { SpatDataFrame df = v->df; Rcpp::List lst = getDataFrame(&df); return lst; } /* Rcpp::List getRasterAttributes(SpatRaster* x) { Rcpp::List lst; if (x->nlyr() > 0) { SpatDataFrame df = x->source[0].cats[0]; lst = getDataFrame(&df); } return lst; } */ Rcpp::DataFrame get_geometryDF(SpatVector* v) { SpatDataFrame df = v->getGeometryDF(); Rcpp::DataFrame out = Rcpp::DataFrame::create( Rcpp::Named("id") = df.iv[0], Rcpp::Named("part") = df.iv[1], Rcpp::Named("x") = df.dv[0], Rcpp::Named("y") = df.dv[1], Rcpp::Named("hole") = df.iv[2] ); return out; } RCPP_EXPOSED_CLASS(SpatSRS) RCPP_EXPOSED_CLASS(SpatExtent) RCPP_EXPOSED_CLASS(SpatMessages) RCPP_EXPOSED_CLASS(SpatOptions) RCPP_EXPOSED_CLASS(SpatCategories) RCPP_EXPOSED_CLASS(SpatDataFrame) RCPP_EXPOSED_CLASS(SpatWindow) RCPP_EXPOSED_CLASS(SpatRasterSource) RCPP_EXPOSED_CLASS(SpatRaster) RCPP_EXPOSED_CLASS(SpatRasterCollection) RCPP_EXPOSED_CLASS(SpatRasterStack) RCPP_EXPOSED_CLASS(SpatVector) RCPP_EXPOSED_CLASS(SpatVectorProxy) RCPP_EXPOSED_CLASS(SpatVectorCollection) RCPP_MODULE(spat){ using namespace Rcpp; class_("SpatSRS") .method("is_lonlat", &SpatSRS::is_lonlat, "") .method("to_meter", &SpatSRS::to_meter, "to_meter") ; class_("SpatExtent") .constructor() .constructor() .method("deepcopy", &SpatExtent::deepCopy, "deepCopy") .property("vector", &SpatExtent::asVector) .property("valid", &SpatExtent::valid) .method("align", &SpatExtent::align, "align") .method("intersect", &SpatExtent::intersect, "intersect") .method("as.points", &SpatExtent::asPoints, "as.points") .method("ceil", &SpatExtent::ceil, "ceil") .method("compare", &SpatExtent::compare, "compare") .method("floor", &SpatExtent::floor, "floor") .method("round", &SpatExtent::round, "round") .method("union", &SpatExtent::unite, "union") .method("sampleRandom", &SpatExtent::sampleRandom) .method("sampleRegular", &SpatExtent::sampleRegular) .method("sample", &SpatExtent::test_sample) ; /* class_("SpatWindow") .field_readonly("full_extent", &SpatWindow::full_extent) .field_readonly("full_nrow", &SpatWindow::full_nrow) .field_readonly("full_ncol", &SpatWindow::full_ncol) .field_readonly("off_row", &SpatWindow::off_row) .field_readonly("off_col", &SpatWindow::off_col) .field_readonly("expand", &SpatWindow::expand) ; */ class_("SpatMessages") .constructor() //.field("success", &SpatMessages::success) .field("has_error", &SpatMessages::has_error) .field("has_warning", &SpatMessages::has_warning) .method("getError", &SpatMessages::getError) .method("getWarnings", &SpatMessages::getWarnings) ; class_("SpatOptions") .constructor() .method("deepcopy", &SpatOptions::deepCopy, "deepCopy") .property("tempdir", &SpatOptions::get_tempdir, &SpatOptions::set_tempdir ) .property("memfrac", &SpatOptions::get_memfrac, &SpatOptions::set_memfrac ) .property("memmax", &SpatOptions::get_memmax, &SpatOptions::set_memmax ) .property("tolerance", &SpatOptions::get_tolerance, &SpatOptions::set_tolerance ) .property("filenames", &SpatOptions::get_filenames, &SpatOptions::set_filenames ) .property("filetype", &SpatOptions::get_filetype, &SpatOptions::set_filetype ) .property("datatype", &SpatOptions::get_datatype, &SpatOptions::set_datatype ) .property("verbose", &SpatOptions::get_verbose, &SpatOptions::set_verbose ) .property("NAflag", &SpatOptions::get_NAflag, &SpatOptions::set_NAflag ) //.property("ncdfcopy", &SpatOptions::get_ncdfcopy, &SpatOptions::set_ncdfcopy ) .property("statistics", &SpatOptions::get_statistics, &SpatOptions::set_statistics ) .property("overwrite", &SpatOptions::get_overwrite, &SpatOptions::set_overwrite ) //.property("append", &SpatOptions::get_append, &SpatOptions::set_append ) .field("datatype_set", &SpatOptions::datatype_set) .field("threads", &SpatOptions::threads) .property("progress", &SpatOptions::get_progress, &SpatOptions::set_progress) .property("ncopies", &SpatOptions::get_ncopies, &SpatOptions::set_ncopies) .property("def_filetype", &SpatOptions::get_def_filetype, &SpatOptions::set_def_filetype ) .property("def_datatype", &SpatOptions::get_def_datatype, &SpatOptions::set_def_datatype ) .property("def_verbose", &SpatOptions::get_def_verbose, &SpatOptions::set_def_verbose ) //.property("def_bandorder", &SpatOptions::get_def_bandorder, &SpatOptions::set_def_bandorder ) .property("todisk", &SpatOptions::get_todisk, &SpatOptions::set_todisk) .field("messages", &SpatOptions::msg, "messages") .field("gdal_options", &SpatOptions::gdal_options) .field("pid", &SpatOptions::pid ) .field("names", &SpatOptions::names) .property("steps", &SpatOptions::get_steps, &SpatOptions::set_steps) // .property("overwrite", &SpatOptions::set_overwrite, &SpatOptions::get_overwrite ) //.field("gdaloptions", &SpatOptions::gdaloptions) ; class_("SpatDataFrame") .constructor() .field_readonly("itype", &SpatDataFrame::itype) .field_readonly("iplace", &SpatDataFrame::iplace) .property("names", &SpatDataFrame::get_names, &SpatDataFrame::set_names) .property("nrow", &SpatDataFrame::nrow, &SpatDataFrame::resize_rows, "nrow") .property("ncol", &SpatDataFrame::ncol, &SpatDataFrame::resize_cols, "ncol") .method("has_error", &SpatDataFrame::hasError) .method("has_warning", &SpatDataFrame::hasWarning) .method("getWarnings", &SpatDataFrame::getWarnings) .method("getError", &SpatDataFrame::getError) .method("add_column_double", (bool (SpatDataFrame::*)(std::vector, std::string name))( &SpatDataFrame::add_column)) .method("add_column_long", (bool (SpatDataFrame::*)(std::vector, std::string name))( &SpatDataFrame::add_column)) .method("add_column_string", (bool (SpatDataFrame::*)(std::vector, std::string name))( &SpatDataFrame::add_column)) .method("remove_column", (bool (SpatDataFrame::*)(std::string field))( &SpatDataFrame::remove_column)) .method("remove_column", (bool (SpatDataFrame::*)(int i))( &SpatDataFrame::remove_column)) .method("get_datatypes", &SpatDataFrame::get_datatypes, "") .method("subset_rows", (SpatDataFrame (SpatDataFrame::*)(std::vector))( &SpatDataFrame::subset_rows), "subset_cols") .method("subset_cols", (SpatDataFrame (SpatDataFrame::*)(std::vector))( &SpatDataFrame::subset_cols), "subset_cols") .method("remove_rows", &SpatDataFrame::remove_rows) .method("cbind", &SpatDataFrame::cbind) .method("rbind", &SpatDataFrame::rbind) .method("values", &getDataFrame, "get data.frame") .method("unique", &SpatDataFrame::unique) .method("write", &SpatDataFrame::write_dbf) .field("messages", &SpatDataFrame::msg, "messages") ; class_("SpatVectorCollection") .constructor() //.property("names", &SpatVectorCollection::get_names, &SpatVectorCollection::set_names) .method("deepcopy", &SpatVectorCollection::deepCopy, "deepCopy") .method("size", &SpatVectorCollection::size, "size") .method("get", &SpatVectorCollection::get, "get") .method("push_back", &SpatVectorCollection::push_back, "push_back") .method("subset", &SpatVectorCollection::subset, "subset") .method("replace", &SpatVectorCollection::replace, "replace") .method("append", &SpatVectorCollection::append, "append") .method("has_error", &SpatVectorCollection::hasError) .method("has_warning", &SpatVectorCollection::hasWarning) .method("getWarnings", &SpatVectorCollection::getWarnings) .method("getError", &SpatVectorCollection::getError) ; class_("SpatCategories") .constructor() .field_readonly("df", &SpatCategories::d, "d") .field("index", &SpatCategories::index, "index") ; class_("SpatVector") .constructor() .constructor() .constructor>() .method("deepcopy", &SpatVector::deepCopy, "deepCopy") .method("wkt", &SpatVector::wkt, "") .method("wkb", &SpatVector::wkb, "") .method("hex", &SpatVector::hex, "") .method("from_hex", &SpatVector::from_hex, "") .method("make_nodes", &SpatVector::make_nodes, "") .method("boundary", &SpatVector::boundary, "") .method("polygonize", &SpatVector::polygonize, "") .method("normalize", &SpatVector::normalize, "") .method("line_merge", &SpatVector::line_merge, "") .method("simplify", &SpatVector::simplify, "") .method("shared_paths", &SpatVector::shared_paths, "") .method("snap", &SpatVector::snap, "") .field_readonly("is_proxy", &SpatVector::is_proxy ) .field_readonly("read_query", &SpatVector::read_query ) .field_readonly("read_extent", &SpatVector::read_extent ) .field_readonly("geom_count", &SpatVector::geom_count) .field_readonly("source", &SpatVector::source) .field_readonly("layer", &SpatVector::source_layer) .field_readonly("df", &SpatVector::df ) .method("has_error", &SpatVector::hasError) .method("has_warning", &SpatVector::hasWarning) .method("getError", &SpatVector::getError) .method("getWarnings", &SpatVector::getWarnings) .method("coordinates", &SpatVector::coordinates) .method("get_geometry", &SpatVector::getGeometry) .method("get_geometryDF", &get_geometryDF) .method("add_column_empty", (void (SpatVector::*)(unsigned dtype, std::string name))( &SpatVector::add_column)) .method("add_column_double", (bool (SpatVector::*)(std::vector, std::string name))( &SpatVector::add_column)) .method("add_column_long", (bool (SpatVector::*)(std::vector, std::string name))( &SpatVector::add_column)) .method("add_column_string", (bool (SpatVector::*)(std::vector, std::string name))( &SpatVector::add_column)) .method("remove_column", (bool (SpatVector::*)(std::string field))( &SpatVector::remove_column)) .method("remove_column", (bool (SpatVector::*)(int i))( &SpatVector::remove_column)) .method("remove_df", &SpatVector::remove_df) .method("get_datatypes", &SpatVector::get_datatypes, "") .method("set_holes", &SpatVector::set_holes, "set_holes") .method("get_holes", &SpatVector::get_holes, "get_holes") .method("remove_holes", &SpatVector::remove_holes, "remove holes") .method("append", &SpatVector::append, "append") .method("cbind", &SpatVector::cbind, "cbind") .method("rbind", &SpatVector::append, "rbind") .method("area", &SpatVector::area, "area") .method("as_lines", &SpatVector::as_lines, "as_lines") .method("as_points", &SpatVector::as_points, "as_points") .method("couldBeLonLat", &SpatVector::could_be_lonlat, "couldBeLonLat") .method("get_crs", &SpatVector::getSRS) .method("set_crs", (bool (SpatVector::*)(std::string crs))( &SpatVector::setSRS)) //.method("prj", &SpatVector::getPRJ) .method("distance_self", (std::vector (SpatVector::*)(bool))( &SpatVector::distance)) .method("distance_other", (std::vector (SpatVector::*)(SpatVector, bool))( &SpatVector::distance)) .method("geosdist_self", (std::vector (SpatVector::*)(bool))( &SpatVector::geos_distance)) .method("geosdist_other", (std::vector (SpatVector::*)(SpatVector, bool))( &SpatVector::geos_distance)) .method("extent", &SpatVector::getExtent, "extent") .method("getDF", &getVectorAttributes, "get attributes") .method("getGeometryWKT", &SpatVector::getGeometryWKT, "getGeometryWKT") .method("isLonLat", &SpatVector::is_lonlat, "is lonlat") .method("length", &SpatVector::length, "length") // .field("srs", &SpatVector::srs, "srs") .field("messages", &SpatVector::msg, "messages") .property("names", &SpatVector::get_names, &SpatVector::set_names) .method("nrow", &SpatVector::nrow, "nrow") .method("ncol", &SpatVector::ncol, "ncol") .method("project", &SpatVector::project, "project") .method("read", &SpatVector::read) .method("setGeometry", &SpatVector::setGeometry) .method("setPointsXY", &SpatVector::setPointsGeometry) .method("setPointsDF", &SpatVector::setPointsDF) .method("size", &SpatVector::size, "size") .method("subset_cols", ( SpatVector (SpatVector::*)(std::vector))( &SpatVector::subset_cols )) .method("subset_rows", ( SpatVector (SpatVector::*)(std::vector))( &SpatVector::subset_rows )) .method("remove_rows", &SpatVector::remove_rows, "remove_rows") .method("type", &SpatVector::type, "type") .method("write", &SpatVector::write) .method("delete_layers", &SpatVector::delete_layers) .method("layer_names", &SpatVector::layer_names) .method("bienvenue", &SpatVector::bienvenue, "bienvenue") .method("allerretour", &SpatVector::allerretour, "allerretour") .method("geos_isvalid", &SpatVector::geos_isvalid, "geos_isvalid") .method("geos_isvalid_msg", &SpatVector::geos_isvalid_msg, "geos_isvalid_msg") .method("aggregate", ( SpatVector (SpatVector::*)(std::string, bool))( &SpatVector::aggregate )) .method("aggregate_nofield", ( SpatVector (SpatVector::*)(bool))( &SpatVector::aggregate )) .method("disaggregate", &SpatVector::disaggregate, "disaggregate") .method("buffer", &SpatVector::buffer, "buffer") .method("centroid", &SpatVector::centroid, "centroid") .method("make_valid2", &SpatVector::make_valid2) .method("flip", &SpatVector::flip) .method("transpose", &SpatVector::transpose) .method("shift", &SpatVector::shift) .method("rescale", &SpatVector::rescale) .method("rotate", &SpatVector::rotate) .method("erase_agg", &SpatVector::erase_agg) .method("erase", ( SpatVector (SpatVector::*)(SpatVector))( &SpatVector::erase )) .method("erase_self", ( SpatVector (SpatVector::*)())( &SpatVector::erase )) .method("gaps", &SpatVector::gaps) .method("symdif", &SpatVector::symdif) .method("cover", &SpatVector::cover) .method("union", ( SpatVector (SpatVector::*)(SpatVector))( &SpatVector::unite )) .method("union_self", ( SpatVector (SpatVector::*)())( &SpatVector::unite )) .method("union_unary", &SpatVector::unaryunion) .method("intersect", &SpatVector::intersect) .method("delauny", &SpatVector::delauny) .method("voronoi", &SpatVector::voronoi) .method("hull", &SpatVector::hull) .method("width", &SpatVector::width) .method("clearance", &SpatVector::clearance) .method("mask", &SpatVector::mask) .method("is_related", &SpatVector::is_related) .method("relate_first", &SpatVector::relateFirst) .method("relate_between", ( std::vector (SpatVector::*)(SpatVector, std::string))( &SpatVector::relate )) .method("relate_within", ( std::vector (SpatVector::*)(std::string, bool))( &SpatVector::relate )) .method("crop_ext", ( SpatVector (SpatVector::*)(SpatExtent))( &SpatVector::crop )) .method("crop_vct", ( SpatVector (SpatVector::*)(SpatVector))( &SpatVector::crop )) .method("near_between", (SpatVector (SpatVector::*)(SpatVector, bool))( &SpatVector::nearest_point)) .method("near_within", (SpatVector (SpatVector::*)())( &SpatVector::nearest_point)) //.method("knearest", &SpatVector::knearest) .method("split", &SpatVector::split) .method("sample", &SpatVector::sample) .method("sampleGeom", &SpatVector::sample_geom) .method("remove_duplicate_nodes", &SpatVector::remove_duplicate_nodes) .method("cross_dateline", &SpatVector::cross_dateline) .method("fix_lonlat_overflow", &SpatVector::fix_lonlat_overflow) .method("densify", &SpatVector::densify) .method("round", &SpatVector::round) ; // class_("SpatRasterSource") /// .field_readonly("has_scale_offset", &SpatRasterSource::has_scale_offset) // .field_readonly("scale", &SpatRasterSource::scale) // .field_readonly("offset", &SpatRasterSource::offset) // .field_readonly("time", &SpatRasterSource::time) // .field("srs", &SpatRasterSource::srs, "srs") //.field_readonly("memory", &SpatRasterSource::memory) // .field_readonly("filename", &SpatRasterSource::filename) //.field_readonly("driver", &SpatRasterSource::driver) //.field_readonly("nrow", &SpatRasterSource::nrow) //.field_readonly("ncol", &SpatRasterSource::ncol) //.field_readonly("nlyr", &SpatRasterSource::nlyr) // .field_readonly("extent", &SpatRasterSource::extent) // .field_readonly("hasWindow", &SpatRasterSource::hasWindow) // .field_readonly("window", &SpatRasterSource::window) //.field_readonly("layers", &SpatRasterSource::layers) //.field_readonly("nlyrfile", &SpatRasterSource::nlyrfile) //.field_readonly("flipped", &SpatRasterSource::flipped) //.field_readonly("rotated", &SpatRasterSource::rotated) // .field_readonly("parameters_changed", &SpatRasterSource::parameters_changed) // ; class_("SpatVectorProxy") .constructor() .field("v", &SpatVectorProxy::v ) .method("deepcopy", &SpatVectorProxy::deepCopy, "deepCopy") ; class_("SpatRaster") .constructor() // .constructor() .constructor, std::vector, std::vector, bool, std::vector, std::vector>() .constructor, std::vector, std::string>() //.finalizer(&SpatRaster_finalizer) .method("fromFiles", &SpatRaster::fromFiles) .method("has_error", &SpatRaster::hasError) .method("has_warning", &SpatRaster::hasWarning) .method("getError", &SpatRaster::getError) .method("getWarnings", &SpatRaster::getWarnings) .method("getMessage", &SpatRaster::getMessage) //.field("name", &SpatRaster::name) .method("getFileBlocksize", &SpatRaster::getFileBlocksize) .method("sources_to_disk", &SpatRaster::sources_to_disk, "sources_to_disk") .method("mem_needs", &SpatRaster::mem_needs, "mem_needs") .method("spatinit", &SpatRaster::gdalogrproj_init, "init") .method("addSource", &SpatRaster::addSource, "addSource") .method("replace", &SpatRaster::replace, "replace") .method("combineSources", &SpatRaster::combineSources, "combineSources") .method("compare_geom", &SpatRaster::compare_geom, "compare_geom") .method("couldBeLonLat", &SpatRaster::could_be_lonlat, "couldBeLonLat") .method("deepcopy", &SpatRaster::deepCopy, "deepCopy") .method("hardcopy", &SpatRaster::hardCopy) .method("get_crs", &SpatRaster::getSRS) .method("set_crs", (bool (SpatRaster::*)(std::string crs))( &SpatRaster::setSRS)) //.field_readonly("prj", &SpatRaster::prj) .property("extent", &SpatRaster::getExtent, &SpatRaster::setExtent ) .method("setWindow", &SpatRaster::setWindow, "") .method("removeWindow", &SpatRaster::removeWindow, "") .method("hasWindow", &SpatRaster::hasWindow, "") //.method("getRasterAtt", &getRasterAttributes, "get attributes") .property("filenames", &SpatRaster::filenames ) .field_readonly("rgb", &SpatRaster::rgb) .field_readonly("rgbtype", &SpatRaster::rgbtype) .method("setRGB", &SpatRaster::setRGB) .method("removeRGB", &SpatRaster::removeRGB) .method("getRGB", &SpatRaster::getRGB) //.method("setAttIndex", &SpatRaster::setAttrIndex, "setAttrIndex") //.method("getAttIndex", &SpatRaster::getAttrIndex, "getAttrIndex") //.method("hasAttributes", &SpatRaster::hasAttributes, "hasAttributes") //.method("getAttributes", &SpatRaster::getAttributes, "getAttributes") //.method("setAttributes", &SpatRaster::setAttributes, "setAttributes") //.method("createAttributes", &SpatRaster::createAttributes, "createAttributes") .method("makeCategorical", &SpatRaster::makeCategorical, "makeCategorical") .method("createCategories", &SpatRaster::createCategories, "createCategories") .method("hasCategories", &SpatRaster::hasCategories, "hasCategories") .method("getCategories", &SpatRaster::getCategories, "getCategories") .method("setCategories", &SpatRaster::setCategories, "setCategories") .method("removeCategories", &SpatRaster::removeCategories, "removeCategories") .method("getLabels", &SpatRaster::getLabels, "getLabels") .method("setLabels", &SpatRaster::setLabels, "setLabels") .method("getCatIndex", &SpatRaster::getCatIndex, "getCatIndex") .method("setCatIndex", &SpatRaster::setCatIndex, "setCatIndex") .method("hasColors", &SpatRaster::hasColors, "hasColors") .method("getColors", &SpatRaster::getColors, "getColors") .method("setColors", &SpatRaster::setColors, "setColors") .method("removeColors", &SpatRaster::removeColors, "removeColors") .property("valueType", &SpatRaster::getValueType) .method("setValueType", &SpatRaster::setValueType) .property("hasRange", &SpatRaster::hasRange ) .property("hasValues", &SpatRaster::hasValues ) .property("inMemory", &SpatRaster::inMemory ) .method("isLonLat", &SpatRaster::is_lonlat, "isLonLat") .method("isGlobalLonLat", &SpatRaster::is_global_lonlat, "isGlobalLonLat") .property("names", &SpatRaster::getNames) .method("get_sourcenames_long", &SpatRaster::getLongSourceNames) .method("set_sourcenames_long", &SpatRaster::setLongSourceNames) .method("get_sourcenames", &SpatRaster::getSourceNames) .method("set_sourcenames", &SpatRaster::setSourceNames) .method("setNAflag", &SpatRaster::setNAflag) .method("getNAflag", &SpatRaster::getNAflag) .property("hasUnit", &SpatRaster::hasUnit) .property("hasTime", &SpatRaster::hasTime) .property("time", &SpatRaster::getTime) .property("timestep", &SpatRaster::getTimeStep) .method("settime", &SpatRaster::setTime) //.property("timestr", &SpatRaster::getTimeStr) .property("depth", &SpatRaster::getDepth) .method("set_depth", &SpatRaster::setDepth) .property("units", &SpatRaster::getUnit) .method("set_units", &SpatRaster::setUnit) .method("size", &SpatRaster::size, "size") .method("nrow", &SpatRaster::nrow, "nrow") .method("ncol", &SpatRaster::ncol, "ncol") .method("nsrc", &SpatRaster::nsrc, "nsrc" ) .field("messages", &SpatRaster::msg, "messages") .method("nlyrBySource", &SpatRaster::nlyrBySource, "nlyrBySource" ) .method("lyrsBySource", &SpatRaster::lyrsBySource, "lyrsBySource" ) .method("getBands", &SpatRaster::getBands, "getBands" ) .method("nlyr", &SpatRaster::nlyr, "nlyr" ) .property("origin", &SpatRaster::origin) .property("range_min", &SpatRaster::range_min ) .property("range_max", &SpatRaster::range_max ) .property("res", &SpatRaster::resolution) // only if SpatRasterSource is exposed // .field_readonly("source", &SpatRaster::source ) .method("collapse_sources", &SpatRaster::collapse_sources, "collapse_sources" ) .method("make_vrt", &SpatRaster::make_vrt, "make_vrt" ) .method("dense_extent", &SpatRaster::dense_extent, "dense_extent") .method("setNames", &SpatRaster::setNames, "setNames" ) .method("setTime", &SpatRaster::setTime, "setTime" ) .method("setDepth", &SpatRaster::setDepth, "setDepth" ) .method("setUnit", &SpatRaster::setUnit, "setUnit" ) .method("set_resolution", &SpatRaster::setResolution, "set resolution") .method("subset", &SpatRaster::subset, "subset") .method("cellFromXY", ( std::vector (SpatRaster::*)(std::vector,std::vector) )( &SpatRaster::cellFromXY )) .method("vectCells", &SpatRaster::vectCells, "vectCells") .method("extCells", &SpatRaster::extCells, "extCells") .method("wmean_rast", (SpatRaster (SpatRaster::*)(SpatRaster, bool, SpatOptions&))( &SpatRaster::weighted_mean )) .method("wmean_vect", (SpatRaster (SpatRaster::*)(std::vector, bool, SpatOptions&))( &SpatRaster::weighted_mean )) .method("cellFromRowCol", ( std::vector (SpatRaster::*)(std::vector,std::vector) )( &SpatRaster::cellFromRowCol )) .method("cellFromRowColCombine", ( std::vector (SpatRaster::*)(std::vector,std::vector) )( &SpatRaster::cellFromRowColCombine )) .method("yFromRow", ( std::vector (SpatRaster::*)(const std::vector&) )( &SpatRaster::yFromRow )) .method("xFromCol", ( std::vector (SpatRaster::*)(const std::vector&) )( &SpatRaster::xFromCol )) .method("colFromX", ( std::vector (SpatRaster::*)(const std::vector&) )( &SpatRaster::colFromX )) .method("rowFromY", ( std::vector (SpatRaster::*)(const std::vector&) )( &SpatRaster::rowFromY )) .method("xyFromCell", ( std::vector< std::vector > (SpatRaster::*)(std::vector&) )( &SpatRaster::xyFromCell )) .method("rowColFromCell", ( std::vector< std::vector > (SpatRaster::*)(std::vector) )( &SpatRaster::rowColFromCell )) .method("readStart", &SpatRaster::readStart, "readStart") .method("readStop", &SpatRaster::readStop, "readStop") .method("readAll", &SpatRaster::readAll, "readAll") .method("readValues", &SpatRaster::readValuesR, "readValues") .method("getValues", &SpatRaster::getValues, "getValues") .method("getBlockSizeR", &getBlockSizeR) .method("getBlockSizeWrite", &getBlockSizeWrite) .method("same", &sameObject) #ifdef useRcpp .method("setValuesRcpp", &SpatRaster::setValuesRcpp) #endif .method("setValues", &SpatRaster::setValues) .method("replaceCellValues", &SpatRaster::replaceCellValues) .method("setRange", &SpatRaster::setRange, "setRange") .method("writeStart", &SpatRaster::writeStart, "writeStart") .method("writeStop", &SpatRaster::writeStop, "writeStop") .method("writeValues", &SpatRaster::writeValues, "writeValues") .method("writeRaster", &SpatRaster::writeRaster, "writeRaster") .method("canProcessInMemory", &SpatRaster::canProcessInMemory, "canProcessInMemory") .method("chunkSize", &SpatRaster::chunkSize, "chunkSize") .method("to_memory", &SpatRaster::to_memory, "to_memory") .method("adjacentMat", &SpatRaster::adjacentMat, "adjacent with matrix") .method("adjacent", &SpatRaster::adjacent, "adjacent") .method("aggregate", &SpatRaster::aggregate, "aggregate") .method("align", &SpatRaster::align, "align") .method("apply", &SpatRaster::apply, "apply") .method("rapply", &SpatRaster::rapply, "rapply") .method("rappvals", &SpatRaster::rappvals, "rappvals") .method("arith_rast", ( SpatRaster (SpatRaster::*)(SpatRaster, std::string, SpatOptions&) )( &SpatRaster::arith )) .method("arith_numb", ( SpatRaster (SpatRaster::*)(std::vector, std::string, bool, SpatOptions&) )( &SpatRaster::arith )) .method("rst_area", &SpatRaster::rst_area, "rst_area") .method("sum_area", &SpatRaster::sum_area, "sum_area") .method("area_by_value", &SpatRaster::area_by_value, "area_by_value") .method("as_points", &SpatRaster::as_points, "as_points") .method("as_lines", &SpatRaster::as_lines, "as_lines") .method("as_polygons", &SpatRaster::as_polygons, "as_polygons") .method("polygonize", &SpatRaster::polygonize, "polygonize") .method("atan2", &SpatRaster::atan_2, "atan2") .method("bilinearValues", &SpatRaster::bilinearValues, "bilin") .method("patches", &SpatRaster::clumps, "patches") .method("boundaries", &SpatRaster::edges, "edges") .method("buffer", &SpatRaster::buffer, "buffer") .method("gridDistance", &SpatRaster::gridDistance) .method("costDistance", &SpatRaster::costDistance) .method("rastDistance", &SpatRaster::distance) .method("rastDirection", &SpatRaster::direction) .method("make_tiles", &SpatRaster::make_tiles) .method("ext_from_rc", &SpatRaster::ext_from_rc) .method("vectDisdirRasterize", &SpatRaster::disdir_vector_rasterize) .method("vectDistanceDirect", &SpatRaster::distance_vector) .method("clamp", &SpatRaster::clamp, "clamp") .method("replaceValues", &SpatRaster::replaceValues, "replace") .method("classify", ( SpatRaster (SpatRaster::*)(std::vector, unsigned, unsigned, bool, bool, bool, bool, SpatOptions&) )( &SpatRaster::reclassify), "reclassify") //.method("source_collapse", &SpatRaster::collapse, "collapse") .method("selRange", &SpatRaster::selRange, "selRange") .method("separate", &SpatRaster::separate, "separate") .method("cover", &SpatRaster::cover, "cover") .method("crop", &SpatRaster::crop, "crop") .method("crop_mask", &SpatRaster::cropmask) .method("cum", &SpatRaster::cum, "cum") .method("disaggregate", &SpatRaster::disaggregate, "disaggregate") .method("expand", &SpatRaster::extend, "extend") .method("extractCell", &SpatRaster::extractCell, "extractCell") .method("extractXY", &SpatRaster::extractXY, "extractXY") // .method("extractXYFlat", &SpatRaster::extractXYFlat, "extractXYflat") .method("extractVector", &SpatRaster::extractVector, "extractVector") .method("extractVectorFlat", &SpatRaster::extractVectorFlat, "extractVectorFlat") .method("flip", &SpatRaster::flip, "flip") .method("focal", &SpatRaster::focal, "focal") .method("focalValues", &SpatRaster::focal_values, "focalValues") .method("count", &SpatRaster::count, "count") .method("freq", &SpatRaster::freq, "freq") .method("geometry", &SpatRaster::geometry, "geometry") .method("get_aggregates", &SpatRaster::get_aggregates, "get_aggregates") .method("get_aggregate_dims", &SpatRaster::get_aggregate_dims2, "get_aggregate_dims") .method("global", &SpatRaster::global, "global") .method("global_weighted_mean", &SpatRaster::global_weighted_mean, "global weighted mean") .method("initf", ( SpatRaster (SpatRaster::*)(std::string, bool, SpatOptions&) )( &SpatRaster::init ), "init fun") .method("initv", ( SpatRaster (SpatRaster::*)(std::vector, SpatOptions&) )( &SpatRaster::init ), "init value") .method("is_in", &SpatRaster::is_in, "isin") .method("is_in_cells", &SpatRaster::is_in_cells, "isincells") .method("isnan", &SpatRaster::isnan, "isnan") .method("isfinite", &SpatRaster::isfinite, "isfinite") .method("isinfinite", &SpatRaster::isinfinite, "isinfinite") .method("logic_rast", ( SpatRaster (SpatRaster::*)(SpatRaster, std::string, SpatOptions&) )( &SpatRaster::logic )) .method("logic_numb", ( SpatRaster (SpatRaster::*)(bool, std::string, SpatOptions&) )( &SpatRaster::logic )) .method("mask_raster", ( SpatRaster (SpatRaster::*)(SpatRaster, bool, std::vector, double, SpatOptions&) )( &SpatRaster::mask), "mask raster") .method("mask_vector", ( SpatRaster (SpatRaster::*)(SpatVector, bool, double, bool, SpatOptions&) )( &SpatRaster::mask), "mask vector") .method("math", &SpatRaster::math, "math") .method("math2", &SpatRaster::math2, "math2") .method("modal", &SpatRaster::modal, "modal") .method("quantile", &SpatRaster::quantile, "quantile") .method("rasterize", &SpatRaster::rasterize, "rasterize") .method("rasterizeLyr", &SpatRaster::rasterizeLyr, "rasterizeLyr") .method("rgb2col", &SpatRaster::rgb2col) .method("rgb2hsx", &SpatRaster::rgb2hsx) .method("hsx2rgb", &SpatRaster::hsx2rgb) .method("reverse", &SpatRaster::reverse, "reverse") .method("rotate", &SpatRaster::rotate, "rotate") //.method("sampleCells", &SpatRaster::sampleCells, "sampleCells") .method("sampleRegularRaster", &SpatRaster::sampleRegularRaster, "sampleRegular") .method("sampleRowColRaster", &SpatRaster::sampleRowColRaster, "sampleRowCol") .method("sampleRegularValues", &SpatRaster::sampleRegularValues, "sampleValues") .method("sampleRowColValues", &SpatRaster::sampleRowColValues, "sampleRowCol") .method("sampleRandomRaster", &SpatRaster::sampleRandomRaster, "sampleRandom") .method("sampleRandomValues", &SpatRaster::sampleRandomValues, "sampleValues") .method("scale", &SpatRaster::scale, "scale") .method("shift", &SpatRaster::shift, "shift") .method("terrain", &SpatRaster::terrain, "terrain") .method("summary", &SpatRaster::summary, "summary") .method("summary_numb", &SpatRaster::summary_numb, "summary_numb") .method("transpose", &SpatRaster::transpose, "transpose") .method("trig", &SpatRaster::trig, "trig") .method("trim", &SpatRaster::trim, "trim") .method("unique", &SpatRaster::unique, "unique") .method("sieve", &SpatRaster::sieveFilter, "sievefilter") .method("rectify", &SpatRaster::rectify) .method("stretch", &SpatRaster::stretch) .method("warp", &SpatRaster::warper) .method("resample", &SpatRaster::resample) .method("zonal", &SpatRaster::zonal) .method("is_true", &SpatRaster::is_true, "is_TRUE") .method("is_false", &SpatRaster::is_true, "is_TRUE") ; class_("SpatRasterCollection") .constructor() .method("deepcopy", &SpatRasterCollection::deepCopy, "deepCopy") .method("has_error", &SpatRasterCollection::has_error) .method("has_warning", &SpatRasterCollection::has_warning) .method("getError", &SpatRasterCollection::getError) .method("getWarnings", &SpatRasterCollection::getWarnings) //.field("messages", &SpatRasterCollection::msg, "messages") .field_readonly("x", &SpatRasterCollection::ds) .method("length", &SpatRasterCollection::size, "size") .method("resize", &SpatRasterCollection::resize, "resize") .method("erase", &SpatRasterCollection::erase, "erase") .method("add", &SpatRasterCollection::push_back, "push_back") .method("merge", &SpatRasterCollection::merge, "merge") .method("mosaic", &SpatRasterCollection::mosaic, "mosaic") .method("morph", &SpatRasterCollection::morph, "morph") ; class_("SpatRasterStack") .constructor() .constructor, bool>() .constructor() .method("deepcopy", &SpatRasterStack::deepCopy) .method("has_error", &SpatRasterStack::has_error) .method("has_warning", &SpatRasterStack::has_warning) .method("getError", &SpatRasterStack::getError) .method("getWarnings", &SpatRasterStack::getWarnings) .method("readStart", &SpatRasterStack::readStart, "readStart") .method("readStop", &SpatRasterStack::readStop, "readStop") .method("nsds", &SpatRasterStack::nsds, "") .method("ncol", &SpatRasterStack::ncol, "") .method("nrow", &SpatRasterStack::nrow, "") .method("getSRS", &SpatRasterStack::getSRS, "") .property("names", &SpatRasterStack::get_names, &SpatRasterStack::set_names) .property("long_names", &SpatRasterStack::get_longnames, &SpatRasterStack::set_longnames) .property("units", &SpatRasterStack::get_units, &SpatRasterStack::set_units) .method("add", &SpatRasterStack::push_back, "") .method("resize", &SpatRasterStack::resize, "") .method("summary", &SpatRasterStack::summary, "summary") .method("summary_numb", &SpatRasterStack::summary_numb, "summary_numb") .method("getsds", &SpatRasterStack::getsds, "") .method("replace", &SpatRasterStack::replace, "") .method("subset", &SpatRasterStack::subset, "") .method("collapse", &SpatRasterStack::collapse , "") .method("extractCell", &SpatRasterStack::extractCell, "extractCell") .method("extractVector", &SpatRasterStack::extractVector, "extractVector") .method("crop", &SpatRasterStack::crop, "") ; } /* SpatRaster SQRT() { SpatRaster r = *this; std::transform(r.values.begin(), r.values.end(), r.values.begin(), (double(*)(double)) sqrt); return r; } SpatRaster SQRTfree(SpatRaster* g) { SpatRaster r = *g; std::transform(r.values.begin(), r.values.end(), r.values.begin(), (double(*)(double)) sqrt); return r; } */ terra/src/ncdf.cpp0000644000175000017500000000052714201035750013727 0ustar nileshnilesh/* #include "spatRaster.h" #include "netcdf.h" // [[Rcpp::export(name = ".readncdf")]] bool readncdf(std::string f) { int ncid; int err = nc_open(f.c_str(), 0, &ncid); Rcpp::Rcout << err << std::endl; if (err != 0) return false; err = nc_close(ncid); Rcpp::Rcout << err << std::endl; if (err != 0) return false; return true; } */ terra/src/progress_interrupts.hpp0000644000175000017500000000213114201035750017156 0ustar nileshnilesh/* * Check for user interruption in C++ code interrupting execution of the current code * * This code has been written by Simon Urbanek * I took it from the R-devel mailing list * in the thread "[Rd] Interrupting C++ code execution" * The mail is dated: 25 april 2011 * * It allows to check for user interruption without * leaving the c++ function that calls it. * * Potential drawbacks according to its author: * The problem with it is that it will eat all errors, even if they were not yours * (e.g. those resulting from events triggered the event loop), so I would not recommend it for general use. * */ #ifndef _RcppProgress_INTERRUPTS_HPP #define _RcppProgress_INTERRUPTS_HPP // N.B: seems the right way to include Rinternals.h in a Rcpp package #include static void chkIntFn(void *dummy) { R_CheckUserInterrupt(); } // this will call the above in a top-level context so it won't longjmp-out of your context inline bool checkInterrupt() { return (R_ToplevelExec(chkIntFn, NULL) == FALSE); } // fix a bug because of the length macro (in sglOptim_1.0.122.1) #undef length #endif terra/src/NA.h0000644000175000017500000000463314201035750012762 0ustar nileshnilesh// Copyright (c) 2018-2020 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include #include template class NA { public: static constexpr T value = std::is_floating_point::value ? NAN : std::numeric_limits::min(); }; // bool has no NA template <> class NA { public: static constexpr unsigned value = false; }; template struct is_string { static const bool value = false; }; template struct is_string> { static const bool value = true; }; /* template <> class NAvalue { public: static constexpr unsigned value = std::numeric_limits::max(); }; */ template bool is_NA(const T v) { if (std::is_floating_point::value) { return std::isnan(v); } else { bool b = v == (NA::value); return b; } } template <> class NA { public: static constexpr unsigned value = std::numeric_limits::max(); }; template void set_NA(std::vector &v, double naflag) { if (!std::isnan(naflag)) { T flag = naflag; T navalue = NA::value; std::replace(v.begin(), v.end(), flag, navalue); } } /* class NA_long { public: static constexpr long value = std::numeric_limits::min(); }; class NA_unsigned { public: static constexpr unsigned value = std::numeric_limits::max(); }; class NA_double { public: static constexpr double value = NAN; }; class NA_float { public: static constexpr float value = NAN; }; bool is_NAN(unsigned v) { return (v == NA_unsigned::value); } bool is_NAN(long v) { return (v == NA_long::value); } bool is_NAN(double v) { return std::isnan(v); } bool is_NAN(float v) { return std::isnan(v); } */ terra/src/crs.cpp0000644000175000017500000001757214201035750013614 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include #include //#include "spatMessages.h" #include "spatRaster.h" #include "string_utils.h" #ifndef useGDAL bool SpatSRS::set(std::string txt, std::string &msg) { proj4 = txt; wkt = ""; return true; } #else #include "ogr_spatialref.h" #include // GDALDriver bool is_ogr_error(OGRErr err, std::string &msg) { if (err != OGRERR_NONE) { switch (err) { case OGRERR_NOT_ENOUGH_DATA: msg = "OGR: Not enough data"; case OGRERR_UNSUPPORTED_GEOMETRY_TYPE: msg = "OGR: Unsupported geometry type"; case OGRERR_CORRUPT_DATA: msg = "OGR: Corrupt data"; case OGRERR_FAILURE: msg = "OGR: Invalid index"; default: msg = "OGR: Error"; } return true; } return false; } bool wkt_from_spatial_reference(const OGRSpatialReference *srs, std::string &wkt, std::string &msg) { char *cp; #if GDAL_VERSION_MAJOR >= 3 const char *options[3] = { "MULTILINE=YES", "FORMAT=WKT2", NULL }; OGRErr err = srs->exportToWkt(&cp, options); #else OGRErr err = srs->exportToWkt(&cp); #endif if (is_ogr_error(err, msg)) { CPLFree(cp); return false; } wkt = std::string(cp); CPLFree(cp); return true; } bool prj_from_spatial_reference(const OGRSpatialReference *srs, std::string &prj, std::string &msg) { char *cp; OGRErr err = srs->exportToProj4(&cp); if (is_ogr_error(err, msg)) { CPLFree(cp); return false; } prj = std::string(cp); CPLFree(cp); return true; } bool string_from_spatial_reference(const OGRSpatialReference *srs, std::vector &out, std::string &msg) { out = std::vector(2, ""); char *cp; #if GDAL_VERSION_MAJOR >= 3 const char *options[3] = { "MULTILINE=NO", "FORMAT=WKT2", NULL }; OGRErr err = srs->exportToWkt(&cp, options); #else OGRErr err = srs->exportToWkt(&cp); #endif if (is_ogr_error(err, msg)) { CPLFree(cp); return false; } out[0] = std::string(cp); err = srs->exportToProj4(&cp); if (is_ogr_error(err, msg)) { CPLFree(cp); return false; } out[1] = std::string(cp); CPLFree(cp); return true; } /* bool SpatSRS::set(OGRSpatialReference *poSRS, std::string &msg) { wkt=""; proj4=""; if (poSRS) { if (! wkt_from_spatial_reference(poSRS, wkt, msg)) { msg = "can't get wkt from srs"; return false; }; if (! prj_from_spatial_reference(poSRS, proj4, msg)) { msg = "can't get proj4 from srs"; return false; }; } return true; } */ double SpatSRS::to_meter() { double out; OGRSpatialReference x; if (wkt.size() < 2) { return NAN; } OGRErr erro = x.SetFromUserInput(wkt.c_str()); if (erro != OGRERR_NONE) { return NAN; } if (x.IsGeographic()) { return 0; } out = x.GetLinearUnits(); return out; } bool SpatSRS::is_same(SpatSRS other, bool ignoreempty) { if (ignoreempty) { if (is_empty() || other.is_empty()) { return true; } } OGRSpatialReference x, y; OGRErr erro = x.SetFromUserInput(wkt.c_str()); if (erro != OGRERR_NONE) { return false; } erro = y.SetFromUserInput(other.wkt.c_str()); if (erro != OGRERR_NONE) { return false; } return x.IsSame(&y); } bool SpatSRS::is_same(std::string other, bool ignoreempty) { if (wkt == "" && other == "") { return true; } else if (wkt == "" || other == "") { return ignoreempty ? true : false; } OGRSpatialReference x, y; OGRErr erro = x.SetFromUserInput(wkt.c_str()); if (erro != OGRERR_NONE) { return false; } erro = y.SetFromUserInput(other.c_str()); if (erro != OGRERR_NONE) { return false; } return x.IsSame(&y); } bool SpatSRS::is_lonlat() { OGRSpatialReference x; if (wkt.size() < 2) { return false; } OGRErr erro = x.SetFromUserInput(wkt.c_str()); if (erro != OGRERR_NONE) { return false; } return x.IsGeographic(); } bool SpatSRS::set(std::string txt, std::string &msg) { wkt=""; proj4=""; lrtrim(txt); if (txt == "") { return true; } else { OGRSpatialReference *srs = new OGRSpatialReference; const char* s = txt.c_str(); if (is_ogr_error(srs->SetFromUserInput(s), msg)) { delete srs; msg = "empty srs"; return false; } if (! wkt_from_spatial_reference(srs, wkt, msg)) { delete srs; msg = "can't get wkt from srs"; return false; }; if (! prj_from_spatial_reference(srs, proj4, msg)) { delete srs; msg = "can't get proj4 from srs"; return false; }; delete srs; return true; } return false; } bool wkt_from_string(std::string input, std::string& wkt, std::string& msg) { lrtrim(input); wkt=""; bool success = false; if (input != "") { OGRSpatialReference *srs = new OGRSpatialReference; const char* s = input.c_str(); if (is_ogr_error(srs->SetFromUserInput(s), msg)) { delete srs; return false; } success = wkt_from_spatial_reference(srs, wkt, msg); delete srs; } return success; } SpatMessages transform_coordinates(std::vector &x, std::vector &y, std::string fromCRS, std::string toCRS) { SpatMessages m; OGRSpatialReference source, target; const char *pszDefFrom = fromCRS.c_str(); OGRErr erro = source.SetFromUserInput(pszDefFrom); if (erro != OGRERR_NONE) { m.setError("input crs is not valid"); return m; } const char *pszDefTo = toCRS.c_str(); erro = target.SetFromUserInput(pszDefTo); if (erro != OGRERR_NONE) { m.setError("output crs is not valid"); return m; } OGRCoordinateTransformation *poCT; poCT = OGRCreateCoordinateTransformation(&source, &target); if( poCT == NULL ) { m.setError( "Cannot do this coordinate transformation" ); return (m); } unsigned failcount = 0; for (size_t i=0; i < x.size(); i++) { if( !poCT->Transform( 1, &x[i], &y[i] ) ) { x[i] = NAN; y[i] = NAN; failcount++; } } OCTDestroyCoordinateTransformation(poCT); if (failcount > 0) { m.addWarning(std::to_string(failcount) + " failed transformations"); } return m; } SpatVector SpatVector::project(std::string crs) { SpatVector s; #ifndef useGDAL s.setError("GDAL is not available"); return(s); #else OGRSpatialReference source, target; std::string vsrs = getSRS("wkt"); const char *pszDefFrom = vsrs.c_str(); OGRErr erro = source.SetFromUserInput(pszDefFrom); if (erro != OGRERR_NONE) { s.setError("input crs is not valid"); return s; } const char *pszDefTo = crs.c_str(); erro = target.SetFromUserInput(pszDefTo); if (erro != OGRERR_NONE) { s.setError("output crs is not valid"); return s; } //CPLSetConfigOption("OGR_CT_FORCE_TRADITIONAL_GIS_ORDER", "YES"); OGRCoordinateTransformation *poCT; poCT = OGRCreateCoordinateTransformation(&source, &target); if( poCT == NULL ) { s.setError( "Cannot do this transformation" ); return(s); } s.setSRS(crs); s.df = df; std::vector keeprows; for (size_t i=0; i < size(); i++) { SpatGeom g = getGeom(i); SpatGeom gg; gg.gtype = g.gtype; for (size_t j=0; j < g.size(); j++) { SpatPart p = g.getPart(j); if (poCT->Transform(p.x.size(), &p.x[0], &p.y[0]) ) { SpatPart pp(p.x, p.y); if (p.hasHoles()) { for (size_t k=0; k < p.nHoles(); k++) { SpatHole h = p.getHole(k); if (poCT->Transform(h.x.size(), &h.x[0], &h.y[0])) { pp.addHole(h.x, h.y); } } } gg.addPart(pp); } } keeprows.push_back(i); s.addGeom(gg); } s.df = df.subset_rows(keeprows); OCTDestroyCoordinateTransformation(poCT); #endif return s; } #endif terra/src/string_utils.cpp0000644000175000017500000001647214201035750015551 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #ifndef STRINGUTILS_H #define STRINGUTILS_H #include #include #include #include #include std::string double_to_string(double x) { std::string s = std::to_string (x); s.erase( s.find_last_not_of('0') + 1, std::string::npos ); s.erase( s.find_last_not_of('.') + 1, std::string::npos ); return s; } void unquote(std::string &s) { s.erase(std::remove(s.begin(), s.end(), '\"'), s.end()); } std::vector string_to_charpnt(std::vector s) { size_t n = s.size(); std::vector out(n + 1); for (size_t i = 0; i < n; i++) { out[i] = (char *) (s[i].c_str()); } out[n] = NULL; return out; } //std::vector string_to_char(std::vector s) { // std::vector charstr(s.c_str(), s.c_str() + s.size() + 1); // return charstr; //} std::vector double_to_string(const std::vector &x, std::string prep) { std::vector out(x.size()); for (size_t i=0; i v, std::string delim) { for (size_t i=0; i<(v.size()-1); i++) { v[i] = v[i] + delim; } std::string s; for (const auto &piece : v) s += piece; return s; } std::vector getlastpart (std::vector s, std::string delim) { std::vector out(s.size()); for (size_t i=0; i= end.length()) { if (s.compare(s.length() - end.length(), s.length(), end) == 0) { return false; } } return true; } void lowercase(std::string &s) { std::transform(s.begin(), s.end(), s.begin(), ::tolower); } void lowercase(std::vector &ss) { for (std::string &s : ss) lowercase(s); } bool is_in_vector(std::string s, std::vector ss) { //std::set sset (ss.begin(), ss.end()); //return sset.find(s) != sset.end(); auto it = std::find (ss.begin(), ss.end(), s); return (it != ss.end()); } int where_in_vector(std::string s, std::vector ss, bool tolower) { int i = -1; if (tolower) lowercase(s); auto it = std::find (ss.begin(), ss.end(), s); if (it != ss.end()) { i = std::distance(ss.begin(), it); } return i; } std::string is_in_set_default(std::string s, std::vector ss, std::string defvalue, bool tolower) { if (tolower) lowercase(s); std::set sset (ss.begin(), ss.end()); if (sset.find(s) == sset.end() ) { s = defvalue; } return s; } std::vector strsplit(std::string s, std::string delimiter){ std::vector out; size_t pos = 0; while ((pos = s.find(delimiter)) != std::string::npos) { out.push_back(s.substr(0, pos)); s.erase(0, pos + delimiter.length()); } out.push_back(s.substr(0, pos)); return out; } std::vector strsplit_first(std::string s, std::string delimiter){ std::vector out; size_t pos = 0; if ((pos = s.find(delimiter)) != std::string::npos) { out.push_back(s.substr(0, pos)); s.erase(0, pos + delimiter.length()); } out.push_back(s); return out; } std::vector str2dbl(std::vector s) { std::vector d (s.size()); std::transform(s.begin(), s.end(), d.begin(), [](const std::string& val) { return std::stod(val); }); return d; } std::vector str2long(std::vector s) { std::vector d (s.size()); std::transform(s.begin(), s.end(), d.begin(), [](const std::string& val) { return std::stol(val); }); return d; } std::vector str2int(std::vector s) { std::vector d (s.size()); std::transform(s.begin(), s.end(), d.begin(), [](const std::string& val) { return std::stoi(val); }); return d; } std::vector dbl2str(std::vector d) { std::vector s (d.size()); std::transform(d.begin(), d.end(), s.begin(), [](double i) { return std::to_string(i); } ); return s; } // trim from start (in place) void ltrim(std::string &s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { return !std::isspace(ch); })); } // trim from end (in place) void rtrim(std::string &s) { s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }).base(), s.end()); } // trim from both ends (in place) void lrtrim(std::string &s) { ltrim(s); rtrim(s); } // trim from start (copying) std::string ltrim_copy(std::string s) { ltrim(s); return s; } // trim from end (copying) std::string rtrim_copy(std::string s) { rtrim(s); return s; } // trim from both ends (copying) std::string lrtrim_copy(std::string s) { lrtrim(s); return s; } void make_valid_names(std::vector &s) { for (size_t i=0; i 1)) { // if (isdigit(s[i][1])) s[i] = "X" + s[i]; // } std::replace(s[i].begin(), s[i].end(), ' ', '.'); } } template std::vector order(const std::vector &v) { std::vector idx(v.size()); std::iota(idx.begin(), idx.end(), 0); std::stable_sort(idx.begin(), idx.end(), [&v](size_t i1, size_t i2) {return v[i1] < v[i2];}); return idx; } void make_unique_names(std::vector &s) { std::vector x = order(s); std::sort(s.begin(), s.end()); std::vector ss = s; unsigned j = 1; for (size_t i=1; i. #include "spatVector.h" #include "string_utils.h" #include "vecmath.h" #include "gdal_alg.h" #include "ogrsf_frmts.h" /* std::vector SpatVector::is_valid() { std::vector out; out.reserve(nrow()); GDALDataset* src; if (!write_ogr(src, "", "layer", "Memory", false, false, true, std::vector())) { if (src != NULL) GDALClose( src ); setError("cannot do it"); return false; } OGRLayer *inLayer = src->GetLayer(0); inLayer->ResetReading(); OGRFeature *inFeature; while( (inFeature = inLayer->GetNextFeature()) != NULL ) { OGRGeometry *poGeometry = inFeature->GetGeometryRef(); out.push_back(poGeometry->IsValid()); OGRFeature::DestroyFeature( inFeature ); } return out; } SpatVector SpatVector::make_valid() { SpatVector out; GDALDataset* src = write_ogr("", "layer", "Memory", false, false, true, std::vector()); OGRLayer *inLayer = src->GetLayer(0); inLayer->ResetReading(); OGRFeature *inFeature; while( (inFeature = inLayer->GetNextFeature()) != NULL ) { OGRGeometry *poGeometry = inFeature->GetGeometryRef(); //OGRGeometry *poGeom = poGeometry->MakeValid(); if (inFeature->SetGeometry( poGeometry ) != OGRERR_NONE) { out.setError("cannot set geometry"); return out; } if (inLayer->SetFeature( inFeature ) != OGRERR_NONE) { out.setError("cannot set feature"); return out; } OGRFeature::DestroyFeature( inFeature ); } std::vector fext; SpatVector fvct; out.read_ogr(src, "", "", fext, fvct, false); GDALClose(src); return out; } */ SpatVector SpatVector::disaggregate() { SpatVector out; out.srs = srs; out.df = df.skeleton(); if (nrow() == 0) { return out; } for (size_t i=0; i idx = df.getIndex(i, uv); for (size_t i=0; i idx = df.getIndex(i, uv); for (size_t i=0; i r; for (size_t j=0; j atts; for (size_t i=0; i size()) { out.setError("invalid index"); return out; } if (x.type() != "polygons") { out.setError("holes must be polygons"); return out; } if (out.geoms[i].size() > 1) { out.setError("selected object has multiple geometries"); } x = x.unaryunion(); SpatPart p = out.geoms[i].parts[0]; SpatGeom g = x.geoms[0]; for (size_t i=0; i geoms_from_ds(GDALDataset* src, int field, int value) { std::vector g; OGRLayer *poLayer = src->GetLayer(0); poLayer->ResetReading(); OGRFeature *poFeature; while( (poFeature = poLayer->GetNextFeature()) != NULL ) { OGRGeometry *poGeometry = poFeature->GetGeometryRef(); g.push_back(poGeometry); } return g; } // create output dataset GDALDataset* dst; // get unique values in field // loop over unique values // for value in uvalues std::vector gvec = geoms_from_ds(src, field, value); OGRGeometry *geom; geom = (OGRGeometry *) gvec.data(); OGRGeometry *gout; gout = geom->UnionCascaded(); // set geometry to output return dst; */ SpatVector SpatVector::shift(double x, double y) { SpatVector out = *this; for (size_t i=0; i < size(); i++) { for (size_t j=0; j < geoms[i].size(); j++) { for (size_t q=0; q < geoms[i].parts[j].x.size(); q++) { out.geoms[i].parts[j].x[q] += x; out.geoms[i].parts[j].y[q] += y; } if (geoms[i].parts[j].hasHoles()) { for (size_t k=0; k < geoms[i].parts[j].nHoles(); k++) { for (size_t q=0; q < geoms[i].parts[j].holes[k].x.size(); q++) { out.geoms[i].parts[j].holes[k].x[q] += x; out.geoms[i].parts[j].holes[k].y[q] += y; } out.geoms[i].parts[j].holes[k].extent.xmin += x; out.geoms[i].parts[j].holes[k].extent.xmax += x; out.geoms[i].parts[j].holes[k].extent.ymin += y; out.geoms[i].parts[j].holes[k].extent.ymax += y; } } out.geoms[i].parts[j].extent.xmin += x; out.geoms[i].parts[j].extent.xmax += x; out.geoms[i].parts[j].extent.ymin += y; out.geoms[i].parts[j].extent.ymax += y; } out.geoms[i].extent.xmin += x; out.geoms[i].extent.xmax += x; out.geoms[i].extent.ymin += y; out.geoms[i].extent.ymax += y; } out.extent.xmin += x; out.extent.xmax += x; out.extent.ymin += y; out.extent.ymax += y; return out; } void resc(double &value, const double &base, const double &f) { value = base + f * (value - base); } SpatVector SpatVector::rescale(double fx, double fy, double x0, double y0) { SpatVector out = *this; for (size_t i=0; i < size(); i++) { for (size_t j=0; j < geoms[i].size(); j++) { for (size_t q=0; q < geoms[i].parts[j].x.size(); q++) { resc(out.geoms[i].parts[j].x[q], x0, fx); resc(out.geoms[i].parts[j].y[q], y0, fy); } if (geoms[i].parts[j].hasHoles()) { for (size_t k=0; k < geoms[i].parts[j].nHoles(); k++) { for (size_t q=0; q < geoms[i].parts[j].holes[k].x.size(); q++) { resc(out.geoms[i].parts[j].holes[k].x[q], x0, fx); resc(out.geoms[i].parts[j].holes[k].y[q], y0, fy); } resc(out.geoms[i].parts[j].holes[k].extent.xmax, x0, fx); resc(out.geoms[i].parts[j].holes[k].extent.ymax, y0, fy); } } resc(out.geoms[i].parts[j].extent.xmin, x0, fx); resc(out.geoms[i].parts[j].extent.xmax, x0, fx); resc(out.geoms[i].parts[j].extent.ymin, y0, fy); resc(out.geoms[i].parts[j].extent.ymax, y0, fy); } resc(out.geoms[i].extent.xmin, x0, fx); resc(out.geoms[i].extent.xmax, x0, fx); resc(out.geoms[i].extent.ymin, y0, fy); resc(out.geoms[i].extent.ymax, y0, fy); } resc(out.extent.xmin, x0, fx); resc(out.extent.xmax, x0, fx); resc(out.extent.ymin, y0, fy); resc(out.extent.ymax, y0, fy); return out; } void dswap(double &a, double&b) { double tmp = a; a = b; b = tmp; } SpatVector SpatVector::transpose() { SpatVector out = *this; for (size_t i=0; i < size(); i++) { for (size_t j=0; j < geoms[i].size(); j++) { out.geoms[i].parts[j].x.swap(out.geoms[i].parts[j].y); if (geoms[i].parts[j].hasHoles()) { for (size_t k=0; k < geoms[i].parts[j].nHoles(); k++) { out.geoms[i].parts[j].holes[k].x.swap(out.geoms[i].parts[j].holes[k].y); dswap(out.geoms[i].parts[j].holes[k].extent.xmin, out.geoms[i].parts[j].holes[k].extent.ymin); dswap(out.geoms[i].parts[j].holes[k].extent.xmax, out.geoms[i].parts[j].holes[k].extent.ymax); } } dswap(out.geoms[i].parts[j].extent.xmin, out.geoms[i].parts[j].extent.ymin); dswap(out.geoms[i].parts[j].extent.xmax, out.geoms[i].parts[j].extent.ymax); } dswap(out.geoms[i].extent.xmin, out.geoms[i].extent.ymin); dswap(out.geoms[i].extent.xmax, out.geoms[i].extent.ymax); } dswap(out.extent.xmin, out.extent.ymin); dswap(out.extent.xmax, out.extent.ymax); return out; } void flipd(double &value, const double &base) { value = base - (value - base); } void flipv(std::vector &v, const double &base) { for (double &d : v) d = base - (d - base); } SpatVector SpatVector::flip(bool vertical) { double x0 = extent.xmin; double y0 = extent.ymin; SpatVector out = *this; bool horizontal = !vertical; for (size_t i=0; i < size(); i++) { for (size_t j=0; j < geoms[i].size(); j++) { if (horizontal) { flipv(out.geoms[i].parts[j].x, x0); flipd(out.geoms[i].parts[j].extent.xmin, x0); flipd(out.geoms[i].parts[j].extent.xmax, x0); dswap(out.geoms[i].parts[j].extent.xmin, out.geoms[i].parts[j].extent.xmax); } else { flipv(out.geoms[i].parts[j].y, y0); flipd(out.geoms[i].parts[j].extent.ymin, y0); flipd(out.geoms[i].parts[j].extent.ymax, y0); dswap(out.geoms[i].parts[j].extent.ymin, out.geoms[i].parts[j].extent.ymax); } if (geoms[i].parts[j].hasHoles()) { for (size_t k=0; k < geoms[i].parts[j].nHoles(); k++) { if (horizontal) { flipv(out.geoms[i].parts[j].holes[k].x, x0); flipd(out.geoms[i].parts[j].holes[k].extent.xmin, x0); flipd(out.geoms[i].parts[j].holes[k].extent.xmax, x0); dswap(out.geoms[i].parts[j].holes[k].extent.xmin, out.geoms[i].parts[j].holes[k].extent.xmax); } else { flipv(out.geoms[i].parts[j].holes[k].y, y0); flipd(out.geoms[i].parts[j].holes[k].extent.ymin, y0); flipd(out.geoms[i].parts[j].holes[k].extent.ymax, y0); dswap(out.geoms[i].parts[j].holes[k].extent.ymin, out.geoms[i].parts[j].holes[k].extent.ymax); } } } } if (horizontal) { flipd(out.geoms[i].extent.xmin, x0); flipd(out.geoms[i].extent.xmax, x0); dswap(out.geoms[i].extent.xmin, out.geoms[i].extent.xmax); } else { flipd(out.geoms[i].extent.ymin, y0); flipd(out.geoms[i].extent.ymax, y0); dswap(out.geoms[i].extent.ymin, out.geoms[i].extent.ymax); } } if (horizontal) { flipd(out.extent.xmin, x0); flipd(out.extent.xmax, x0); dswap(out.extent.xmin, out.extent.xmax); } else { flipd(out.extent.ymin, y0); flipd(out.extent.ymax, y0); dswap(out.extent.ymin, out.extent.ymax); } return out; } void rotit(std::vector &x, std::vector &y, const double &x0, const double &y0, const double &cos_angle, const double &sin_angle) { for (size_t i=0; i. #include #include #include #include #include /* std::vector mean2d(const std::vector> &x) { size_t n = x[0].size(); size_t nn = x.size(); std::vector out(n, NAN); size_t d; double v; for (size_t i=0; i 0) { out[i] = v / d; } } return out; } */ void na_omit(std::vector &x) { x.erase(std::remove_if(std::begin(x), std::end(x), [](const double& value) { return std::isnan(value); }), std::end(x)); } void vector_minmax(std::vector v, double &min, int &imin, double &max, int &imax) { std::vector::size_type p=0; imax = -1; imin=-1; min = std::numeric_limits::max(); max = std::numeric_limits::lowest(); for (auto &val : v) { if (!std::isnan(val)) { if (val > max) { imax = p; max = val; } if (val < min) { imin = p; min = val; } } p++; } if (imax == -1) { max = NAN; min = NAN; } } double roundn(double x, int n){ double d = pow(10.0, n); return std::round(x * d) / d; } double signif(double x, unsigned n) { double b = x; unsigned i; for (i = 0; b >= 1; ++i) { b = b / 10; } int d = n-i; return roundn(x, d); } bool is_equal(double a, double b, double tolerance=10.0) { double tol = std::max(tolerance, std::abs(std::min(a,b))) * std::numeric_limits::epsilon(); return ((a==b) || (std::abs(a-b) < tol) ); } bool about_equal(double a, double b, double tolerance) { return ((a==b) || (std::abs(a-b) < tolerance)); } bool is_equal_relative(double a, double b, double tolerance) { tolerance = std::max(fabs(a), fabs(b)) * tolerance; return about_equal(a, b, tolerance); } bool is_equal_range(double x, double y, double range, double tolerance) { return (fabs(x - y) / range) < tolerance ; } double median(const std::vector& v) { size_t n = v.size(); std::vector vv; vv.reserve(n); for (size_t i=0; i movingMedian(const std::vector &x, size_t n) { std::vector out(x.size()); std::vector d(n, NAN); size_t half = (n/2); size_t half1 = half+1; // fill left side for (size_t i=0; i v; for (size_t i=half; i(x.begin()+i-half, x.begin()+i+half1); out[i] = median(v); } // right side int j=0; for (size_t i=maxn; i values, unsigned ties, bool narm, std::default_random_engine rgen, std::uniform_real_distribution dist) { if (narm) { na_omit(values); } size_t n = values.size(); if (n == 0) return (NAN); if (n == 1) return (values[0]); std::vector counts(n, 0); if (ties < 3) { std::sort(values.begin(), values.end()); } for (size_t i=0; i counts[maxCount]) { maxCount = i; } } // last } else if (ties == 1) { for (size_t i = 1; i < n; ++i) { if (counts[i] >= counts[maxCount]) { maxCount = i; } } // dont care (first, but not sorted) } else if (ties == 2) { for (size_t i = 1; i < n; ++i) { if (counts[i] > counts[maxCount]) { maxCount = i; } } // random } else if (ties == 3) { size_t tieCount = 1; for (size_t i = 1; i < n; ++i) { if (counts[i] > counts[maxCount]) { maxCount = i; tieCount = 1; } else if (counts[i] == counts[maxCount]) { tieCount++; double rand = dist(rgen); if (rand < (1 / tieCount)) { maxCount = i; } } } } else { size_t tieCount = 1; for (size_t i = 1; i < n; ++i) { if (counts[i] > counts[maxCount]) { maxCount = i; tieCount = 1; } else if (counts[i] == counts[maxCount]) { tieCount++; } } if (tieCount > 1 ) { return(NAN); } } return values[maxCount]; } terra/src/Makevars.win0000644000175000017500000000204214201035750014573 0ustar nileshnileshVERSION = 3.2.1 RWINLIB = ../windows/gdal3-$(VERSION) TARGET = lib$(subst gcc,,$(COMPILED_BY))$(R_ARCH) PKG_CPPFLAGS =\ -I$(RWINLIB)/include/gdal-3.2.1 \ -I$(RWINLIB)/include/geos-3.9.0 \ -I$(RWINLIB)/include/proj-7.2.1 # -I$(RWINLIB)/include/netcdf-4.7.3 # -DPROJ_H_API PKG_LIBS = \ -L$(RWINLIB)/$(TARGET) \ -L$(RWINLIB)/lib$(R_ARCH)$(CRT) \ -lgdal -lsqlite3 -lspatialite -lproj -lgeos_c -lgeos \ -ljson-c -lnetcdf -lmariadbclient -lpq -lpgport -lpgcommon \ -lwebp -lcurl -lssh2 -lssl \ -lhdf5_hl -lhdf5 -lexpat -lfreexl -lcfitsio \ -lmfhdf -lhdf -lxdr -lpcre \ -lopenjp2 -ljasper -lpng -ljpeg -ltiff -lgeotiff -lgif -lxml2 -llzma -lz \ -lodbc32 -lodbccp32 -liconv -lpsapi -lwldap32 -lsecur32 -lgdi32 -lnormaliz \ -lcrypto -lcrypt32 -lws2_32 -lshlwapi CXX_STD = CXX11 all: clean winlibs winlibs: mkdir -p ../inst "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" --vanilla "../tools/winlibs.R" $(VERSION) cp -r $(RWINLIB)/share/gdal ../inst/ cp -r $(RWINLIB)/share/proj ../inst/ clean: rm -f $(SHLIB) $(OBJECTS) .PHONY: all winlibs clean terra/src/geos_spat.h0000644000175000017500000005557414201035750014462 0ustar nileshnilesh#define GEOS_USE_ONLY_R_API #include #if GEOS_VERSION_MAJOR == 3 # if GEOS_VERSION_MINOR >= 5 # define GEOS350 # endif # if GEOS_VERSION_MINOR == 6 # if GEOS_VERSION_PATCH >= 1 # define GEOS361 # endif # endif # if GEOS_VERSION_MINOR >= 7 # define GEOS361 # define GEOS370 # endif # if GEOS_VERSION_MINOR >= 8 # define GEOS361 # define GEOS370 # define GEOS380 # endif #else # if GEOS_VERSION_MAJOR > 3 # define GEOS350 # define GEOS370 # define GEOS361 # endif #endif #include "spatVector.h" #include #include #include #include using GeomPtr = std::unique_ptr >; static GeomPtr geos_ptr(GEOSGeometry* g, GEOSContextHandle_t hGEOSctxt) { auto deleter = std::bind(GEOSGeom_destroy_r, hGEOSctxt, std::placeholders::_1); return GeomPtr(g, deleter); } using PrepGeomPtr= std::unique_ptr >; static PrepGeomPtr geos_ptr(const GEOSPreparedGeometry* pg, GEOSContextHandle_t hGEOSctxt) { auto deleter = std::bind(GEOSPreparedGeom_destroy_r, hGEOSctxt, std::placeholders::_1); return PrepGeomPtr(pg, deleter); } #ifdef useRcpp #include "Rcpp.h" template inline void warnNoCall(const char* fmt, Args&&... args ) { Rf_warningcall(R_NilValue, tfm::format(fmt, std::forward(args)... ).c_str()); } template inline void NORET errNoCall(const char* fmt, Args&&... args) { throw Rcpp::exception(tfm::format(fmt, std::forward(args)... ).c_str(), false); } static void __errorHandler(const char *fmt, ...) { char buf[BUFSIZ], *p; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); p = buf + strlen(buf) - 1; if(strlen(buf) > 0 && *p == '\n') *p = '\0'; errNoCall(buf); return; } static void __warningHandler(const char *fmt, ...) { char buf[BUFSIZ], *p; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); p = buf + strlen(buf) - 1; if(strlen(buf) > 0 && *p == '\n') *p = '\0'; warnNoCall(buf); return; } #else #include static void __errorHandler(const char *fmt, ...) { char buf[BUFSIZ], *p; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); p = buf + strlen(buf) - 1; if(strlen(buf) > 0 && *p == '\n') *p = '\0'; std::cout << buf << std::endl; return; } static void __warningHandler(const char *fmt, ...) { char buf[BUFSIZ], *p; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); p = buf + strlen(buf) - 1; if(strlen(buf) > 0 && *p == '\n') *p = '\0'; std::cout << buf << std::endl; return; } #endif void geos_finish(GEOSContextHandle_t ctxt) { #ifdef GEOS350 GEOS_finish_r(ctxt); #else finishGEOS_r(ctxt); #endif } GEOSContextHandle_t geos_init(void) { #ifdef GEOS350 GEOSContextHandle_t ctxt = GEOS_init_r(); GEOSContext_setNoticeHandler_r(ctxt, __warningHandler); GEOSContext_setErrorHandler_r(ctxt, __errorHandler); return ctxt; #else return initGEOS_r((GEOSMessageHandler) __warningHandler, (GEOSMessageHandler) __errorHandler); #endif } static void __warningIgnore(const char *fmt, ...) { return; } GEOSContextHandle_t geos_init2(void) { #ifdef GEOS350 GEOSContextHandle_t ctxt = GEOS_init_r(); GEOSContext_setNoticeHandler_r(ctxt, __warningIgnore); GEOSContext_setErrorHandler_r(ctxt, __errorHandler); return ctxt; #else return initGEOS_r((GEOSMessageHandler) __warningIgnore, (GEOSMessageHandler) __errorHandler); #endif } GEOSGeometry* geos_line(const std::vector &x, const std::vector &y, GEOSContextHandle_t hGEOSCtxt) { GEOSCoordSequence *pseq; size_t n = x.size(); pseq = GEOSCoordSeq_create_r(hGEOSCtxt, n, 2); for (size_t i = 0; i < n; i++) { GEOSCoordSeq_setX_r(hGEOSCtxt, pseq, i, x[i]); GEOSCoordSeq_setY_r(hGEOSCtxt, pseq, i, y[i]); } GEOSGeometry* g = GEOSGeom_createLineString_r(hGEOSCtxt, pseq); // GEOSCoordSeq_destroy(pseq); return g; } GEOSGeometry* geos_linearRing(const std::vector &x, const std::vector &y, GEOSContextHandle_t hGEOSCtxt) { GEOSCoordSequence *pseq; size_t n = x.size(); pseq = GEOSCoordSeq_create_r(hGEOSCtxt, n, 2); for (size_t i = 0; i < n; i++) { GEOSCoordSeq_setX_r(hGEOSCtxt, pseq, i, x[i]); GEOSCoordSeq_setY_r(hGEOSCtxt, pseq, i, y[i]); } GEOSGeometry* g = GEOSGeom_createLinearRing_r(hGEOSCtxt, pseq); // GEOSCoordSeq_destroy(pseq); return g; } GEOSGeometry* geos_polygon(const std::vector &x, const std::vector &y, std::vector> &hx, std::vector> &hy, GEOSContextHandle_t hGEOSCtxt) { GEOSGeometry* shell = geos_linearRing(x, y, hGEOSCtxt); size_t nh = hx.size(); std::vector holes; holes.reserve(nh); size_t nh2 = 0; for (size_t i=0; i> &hx, std::vector> &hy) { size_t nh = p.nHoles(); hx.resize(0); hy.resize(0); hx.reserve(nh); hy.reserve(nh); if (nh == 0) return; for (size_t i=0; i holes; holes.reserve(g.nHoles()); for (size_t k=0; k < g.nHoles(); k++) { SpatHole h = g.getHole(k); GEOSGeometry* glr = geos_linearRing(h.x, h.y, hGEOSCtxt); if (glr != NULL) { holes.push_back(glr); nh++; } } GEOSGeometry* geom = GEOSGeom_createPolygon_r(hGEOSCtxt, shell, &holes[0], nh); return geom; } else { GEOSGeometry* geom = GEOSGeom_createPolygon_r(hGEOSCtxt, shell, NULL, 0); return geom; } } std::vector geos_geoms(SpatVector *v, GEOSContextHandle_t hGEOSCtxt) { size_t n = v->size(); std::vector g; g.reserve(n); std::string vt = v->type(); if (vt == "points") { for (size_t i=0; igetGeom(i); size_t np = svg.size(); GEOSCoordSequence *pseq; std::vector geoms; geoms.reserve(np); for (size_t j = 0; j < np; j++) { //SpatPart svp = svg.getPart(j); pseq = GEOSCoordSeq_create_r(hGEOSCtxt, 1, 2); GEOSCoordSeq_setX_r(hGEOSCtxt, pseq, 0, svg.parts[j].x[0]); GEOSCoordSeq_setY_r(hGEOSCtxt, pseq, 0, svg.parts[j].y[0]); GEOSGeometry* pt = GEOSGeom_createPoint_r(hGEOSCtxt, pseq); if (pt != NULL) { geoms.push_back(pt); } } GEOSGeometry* gcol = (np == 1) ? geoms[0] : GEOSGeom_createCollection_r(hGEOSCtxt, GEOS_MULTIPOINT, &geoms[0], np); g.push_back( geos_ptr(gcol, hGEOSCtxt) ); } } else if (vt == "lines") { // gp = NULL; for (size_t i=0; igetGeom(i); size_t np = svg.size(); std::vector geoms; geoms.reserve(np); for (size_t j=0; j < np; j++) { //SpatPart svp = svg.getPart(j); GEOSGeometry* gp = geos_line(svg.parts[j].x, svg.parts[j].y, hGEOSCtxt); if (gp != NULL) { geoms.push_back(gp); } } GEOSGeometry* gcol = (geoms.size() == 1) ? geoms[0] : GEOSGeom_createCollection_r(hGEOSCtxt, GEOS_MULTILINESTRING, &geoms[0], np); g.push_back( geos_ptr(gcol, hGEOSCtxt) ); } } else { // polygons std::vector> hx, hy; for (size_t i=0; igetGeom(i); size_t np = svg.size(); std::vector geoms; geoms.reserve(np); for (size_t j=0; j < np; j++) { SpatPart svp = svg.getPart(j); //getHoles(svp, hx, hy); //GEOSGeometry* gp = geos_polygon(svp.x, svp.y, hx, hy, hGEOSCtxt); GEOSGeometry* gp = geos_polygon2(svp, hGEOSCtxt); if (gp != NULL) { geoms.push_back(gp); } } //Rcpp::Rcout << np << std::endl; GEOSGeometry* gcol = (geoms.size() == 1) ? geoms[0] : GEOSGeom_createCollection_r(hGEOSCtxt, GEOS_MULTIPOLYGON, &geoms[0], geoms.size()); g.push_back( geos_ptr(gcol, hGEOSCtxt)); } } return g; } SpatVector vect_from_geos(std::vector &geoms , GEOSContextHandle_t hGEOSCtxt, std::string vt) { SpatVector out; SpatVector v; size_t ng = geoms.size(); std::vector gid, gp, hole; std::vector x, y; bool xok, yok; if ((vt == "points") | (vt == "lines")) { for(size_t i = 0; i < ng; i++) { GEOSGeometry* g = geoms[i].get(); size_t np = GEOSGetNumGeometries_r(hGEOSCtxt, g); for(size_t j = 0; j &x, std::vector &y, std::vector &gid, std::vector &gp, std::vector &hole, std::string &msg) { const GEOSCoordSequence* crds = GEOSGeom_getCoordSeq_r(hGEOSCtxt, part); int npts = -1; npts = GEOSGetNumCoordinates_r(hGEOSCtxt, part); if (npts < 0) { msg = "GEOS exception 9"; return false; } double xvalue = 0; double yvalue = 0; for (int p=0; p < npts; p++) { bool xok = GEOSCoordSeq_getX_r(hGEOSCtxt, crds, p, &xvalue); bool yok = GEOSCoordSeq_getY_r(hGEOSCtxt, crds, p, &yvalue); if (xok & yok) { x.push_back(xvalue); y.push_back(yvalue); gid.push_back(i); gp.push_back(j); hole.push_back(0); } } return true; } bool polysFromGeom(GEOSContextHandle_t hGEOSCtxt, const GEOSGeometry* part, const unsigned i, const unsigned j, std::vector &x, std::vector &y, std::vector &gid, std::vector &gp, std::vector &hole, std::string &msg) { const GEOSGeometry* ring = GEOSGetExteriorRing_r(hGEOSCtxt, part); const GEOSCoordSequence* crds = GEOSGeom_getCoordSeq_r(hGEOSCtxt, ring); int npts = -1; npts = GEOSGetNumCoordinates_r(hGEOSCtxt, ring); if (npts < 0) { msg = "exception 99"; return false; } double xvalue = 0; double yvalue = 0; for (int p=0; p < npts; p++) { bool xok = GEOSCoordSeq_getX_r(hGEOSCtxt, crds, p, &xvalue); bool yok = GEOSCoordSeq_getY_r(hGEOSCtxt, crds, p, &yvalue); if (xok & yok) { x.push_back(xvalue); y.push_back(yvalue); gid.push_back(i); gp.push_back(j); hole.push_back(0); } } int nholes = GEOSGetNumInteriorRings_r(hGEOSCtxt, part); for (int h=0; h < nholes; h++) { const GEOSGeometry* ring = GEOSGetInteriorRingN_r(hGEOSCtxt, part, h); const GEOSCoordSequence* crds = GEOSGeom_getCoordSeq_r(hGEOSCtxt, ring); int npts = -1; npts = GEOSGetNumCoordinates_r(hGEOSCtxt, ring); if (npts < 0) { msg = "exception 123"; return false; } double xvalue = 0; double yvalue = 0; for (int p=0; p < npts; p++) { bool xok = GEOSCoordSeq_getX_r(hGEOSCtxt, crds, p, &xvalue); bool yok = GEOSCoordSeq_getY_r(hGEOSCtxt, crds, p, &yvalue); if (xok & yok) { x.push_back(xvalue); y.push_back(yvalue); gid.push_back(i); gp.push_back(j); hole.push_back(h+1); } } } return true; } void emptyGeom(const unsigned i, std::vector &x, std::vector &y, std::vector &gid, std::vector &gp, std::vector &hole) { x.push_back(NAN); y.push_back(NAN); gid.push_back(i); gp.push_back(0); hole.push_back(0); } SpatVectorCollection coll_from_geos(std::vector &geoms, GEOSContextHandle_t hGEOSCtxt, const std::vector &ids = std::vector(), bool keepnull=true, bool increment = true) { SpatVectorCollection out; std::vector pt_gid, pt_gp, pt_hole; std::vector ln_gid, ln_gp, ln_hole; std::vector pl_gid, pl_gp, pl_hole; std::vector pt_x, pt_y, ln_x, ln_y, pl_x, pl_y; std::vector pts_ids, lin_ids, pol_ids; bool track_ids = ids.size() > 0; if (track_ids) { pol_ids.reserve(geoms.size()); } std::string msg; size_t ng = geoms.size(); size_t f = 0; for(size_t i = 0; i < ng; i++) { const GEOSGeometry* g = geoms[i].get(); char* geostype = GEOSGeomType_r(hGEOSCtxt, g); std::string gt = geostype; free(geostype); size_t np = GEOSGetNumGeometries_r(hGEOSCtxt, g); if (gt == "Point" || gt == "MultiPoint") { if (np == 0 && keepnull) { emptyGeom(f, pt_x, pt_y, pt_gid, pt_gp, pt_hole); } for(size_t j = 0; j 0) { SpatVector v; v.setGeometry("polygons", pl_gid, pl_gp, pl_x, pl_y, pl_hole); if (track_ids) v.df.add_column(pol_ids, "ids"); out.push_back(v); //Rcpp::Rcout << "pls" << std::endl; } if (ln_x.size() > 0) { SpatVector v; v.setGeometry("lines", ln_gid, ln_gp, ln_x, ln_y, ln_hole); if (track_ids) v.df.add_column(lin_ids, "ids"); out.push_back(v); //Rcpp::Rcout << "lns" << std::endl; } if (pt_x.size() > 0) { SpatVector v; v.setGeometry("points", pt_gid, pt_gp, pt_x, pt_y, pt_hole); if (track_ids) v.df.add_column(pts_ids, "ids"); out.push_back(v); //Rcpp::Rcout << "pts" << std::endl; } return out; } /* old version no ids SpatVectorCollection coll_from_geos(std::vector &geoms, GEOSContextHandle_t hGEOSCtxt, bool keepnull=true, bool increment = true) { SpatVectorCollection out; std::vector pt_gid, pt_gp, pt_hole; std::vector ln_gid, ln_gp, ln_hole; std::vector pl_gid, pl_gp, pl_hole; std::vector pt_x, pt_y, ln_x, ln_y, pl_x, pl_y; std::string msg; size_t ng = geoms.size(); size_t f = 0; for(size_t i = 0; i < ng; i++) { const GEOSGeometry* g = geoms[i].get(); char* geostype = GEOSGeomType_r(hGEOSCtxt, g); std::string gt = geostype; free(geostype); size_t np = GEOSGetNumGeometries_r(hGEOSCtxt, g); if (gt == "Point" || gt == "MultiPoint") { if (np == 0 && keepnull) { emptyGeom(f, pt_x, pt_y, pt_gid, pt_gp, pt_hole); } for(size_t j = 0; j 0) { SpatVector v; v.setGeometry("polygons", pl_gid, pl_gp, pl_x, pl_y, pl_hole); out.push_back(v); //Rcpp::Rcout << "pls" << std::endl; } if (ln_x.size() > 0) { SpatVector v; v.setGeometry("lines", ln_gid, ln_gp, ln_x, ln_y, ln_hole); out.push_back(v); //Rcpp::Rcout << "lns" << std::endl; } if (pt_x.size() > 0) { SpatVector v; v.setGeometry("points", pt_gid, pt_gp, pt_x, pt_y, pt_hole); out.push_back(v); //Rcpp::Rcout << "pts" << std::endl; } return out; } */ terra/src/string_utils.h0000644000175000017500000000331514201035750015206 0ustar nileshnilesh #ifndef STRINGUTILS_GUARD #define STRINGUTILS_GUARD #include #include void unquote(std::string &s); std::string double_to_string(double x); std::vector double_to_string(const std::vector &x, std::string prep); std::vector string_to_charpnt(std::vector s); std::string concatenate(std::vector v, std::string delim); void lowercase(std::string &s); void lowercase(std::vector &ss); std::string is_in_set_default(std::string s, std::vector ss, std::string defvalue, bool tolower); int where_in_set(std::string s, std::vector ss, bool tolower); bool is_in_vector(std::string s, std::vector ss); int where_in_vector(std::string s, std::vector ss, bool tolower); std::vector getlastpart (std::vector s, std::string delim); std::vector strsplit(std::string s, std::string delimiter); std::vector strsplit_first(std::string s, std::string delimiter); std::vector str2dbl(std::vector s); std::vector str2int(std::vector s); std::vector str2long(std::vector s); std::vector dbl2str(std::vector d); void lrtrim(std::string &s); std::string lrtrim_copy(std::string s); bool in_string(const std::string &x, std::string part); bool ends_on(std::string const &s, std::string const &end); void make_unique_names(std::vector &s); void make_valid_names(std::vector &s); void str_replace(std::string& str, const std::string& from, const std::string& to); size_t str_replace_all(std::string& str, const std::string& from, const std::string& to); #endif terra/src/write.cpp0000644000175000017500000003104714201035750014150 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include "spatRaster.h" #include "file_utils.h" #include "string_utils.h" #include "math_utils.h" bool SpatRaster::writeValuesMem(std::vector &vals, size_t startrow, size_t nrows) { if (vals.size() == size()) { source[0].values = std::move(vals); return true; } if (nlyr() == 1) { source[0].values.insert(source[0].values.end(), vals.begin(), vals.end()); return true; } if (source[0].values.size() == 0) { // && startrow != 0 && startcol != 0) { source[0].values = std::vector(size(), NAN); } size_t nc = ncell(); size_t ncols = ncol(); size_t chunk = nrows * ncols; for (size_t i=0; i &vals, size_t startrow, size_t nrows, size_t startcol, size_t ncols) { if (source[0].values.size() == 0) { // && startrow != 0 && startcol != 0) { source[0].values = std::vector(size(), NAN); } size_t nc = ncell(); size_t chunk = nrows * ncols; for (size_t i=0; i ff = filenames(); for (size_t i=0; i bool SpatRaster::differentFilenames(std::vector outf) { std::vector inf = filenames(); for (size_t i=0; i outf, bool &duplicates, bool &empty) { std::vector inf = filenames(); duplicates = false; empty = false; for (size_t j=0; j outf.size()) { duplicates = true; return false; } return true; } SpatRaster SpatRaster::writeRaster(SpatOptions &opt) { // here we could check if we can simple make a copy if // a) the SpatRaster is backed by a file // b) there are no write options SpatRaster out = geometry(nlyr(), true, true, true); if (!hasValues()) { out.setError("there are no cell values"); return out; } // recursive writing of layers std::vector fnames = opt.get_filenames(); bool dups, empty; if (!differentFilenames(fnames, dups, empty)) { if (dups) { out.setError("duplicate filenames"); } else if (empty) { out.setError("empty filename"); } else { out.setError("source and target filename cannot be the same"); } return(out); } size_t nl = nlyr(); if (fnames.size() > 1) { if (fnames.size() != nl) { out.setError("the number of filenames should either be one, or equal to the number of layers"); return out; } else { bool overwrite = opt.get_overwrite(); std::string errmsg; for (size_t i=0; i v; readBlock(v, out.bs, i); if (!out.writeBlock(v, i)) { readStop(); out.writeStop(); return out; } } out.writeStop(); readStop(); return out; } bool SpatRaster::writeStart(SpatOptions &opt) { if (opt.names.size() == nlyr()) { setNames(opt.names); } std::vector fnames = opt.get_filenames(); if (fnames.size() > 1) { addWarning("only the first filename supplied is used"); } std::string filename = fnames[0]; if (filename == "") { if (!canProcessInMemory(opt)) { std::string extension = ".tif"; filename = tempFile(opt.get_tempdir(), opt.pid, extension); opt.set_filenames({filename}); opt.gdal_options = {"COMPRESS=NONE"}; } } bs = getBlockSize(opt); if (filename != "") { // open GDAL filestream #ifdef useGDAL if (! writeStartGDAL(opt) ) { return false; } #else setError("GDAL is not available"); return false; #endif } else if ((nlyr() == 1) && (bs.n > 1)) { source[0].values.reserve(ncell()); } if (source[0].open_write) { addWarning("file was already open"); } source[0].open_write = true; source[0].filename = filename; //bs = getBlockSize(opt); #ifdef useRcpp if (opt.verbose) { std::vector mems = mem_needs(opt); double gb = 1073741824 / 8; //{memneed, memavail, frac, csize, inmem} ; // << "max vect size : " << roundn(mems.max_size() / gb, 2) << " GB" << std::endl; Rcpp::Rcout<< "memory avail. : " << roundn(mems[1] / gb, 2) << " GB" << std::endl; Rcpp::Rcout<< "memory allow. : " << roundn(mems[2] * mems[1] / gb, 2) << " GB" << std::endl; Rcpp::Rcout<< "memory needed : " << roundn(mems[0] / gb, 3) << " GB" << " (" << opt.ncopies << " copies)" << std::endl; std::string inmem = mems[4] < 0.5 ? "false" : "true"; Rcpp::Rcout<< "in memory : " << inmem << std::endl; Rcpp::Rcout<< "block size : " << mems[3] << " rows" << std::endl; Rcpp::Rcout<< "n blocks : " << bs.n << std::endl; Rcpp::Rcout<< "pb : " << opt.show_progress(bs.n) << std::endl; Rcpp::Rcout<< std::endl; } if (opt.progressbar) { unsigned long steps = bs.n+2; pbar = new Progress(steps, opt.show_progress(bs.n)); pbar->increment(); progressbar = true; } else { progressbar = false; } #endif return true; } bool SpatRaster::writeValues(std::vector &vals, size_t startrow, size_t nrows) { bool success = true; if (!source[0].open_write) { setError("cannot write (no open file)"); return false; } if ((startrow + nrows) > nrow()) { setError("incorrect start and/or nrows value"); return false; } if (source[0].driver == "gdal") { #ifdef useGDAL success = writeValuesGDAL(vals, startrow, nrows, 0, ncol()); #else setError("GDAL is not available"); return false; #endif } else { success = writeValuesMem(vals, startrow, nrows); } #ifdef useRcpp if (progressbar) { if (Progress::check_abort()) { pbar->cleanup(); delete pbar; setError("aborted"); return(false); } pbar->increment(); } #endif return success; } bool SpatRaster::writeValuesRect(std::vector &vals, size_t startrow, size_t nrows, size_t startcol, size_t ncols) { bool success = true; if (!source[0].open_write) { setError("cannot write (no open file)"); return false; } if ((startrow + nrows) > nrow()) { setError("incorrect start and/or nrows value"); return false; } if (source[0].driver == "gdal") { #ifdef useGDAL success = writeValuesGDAL(vals, startrow, nrows, startcol, ncols); #else setError("GDAL is not available"); return false; #endif } else { success = writeValuesMemRect(vals, startrow, nrows, startcol, ncols); } #ifdef useRcpp if (progressbar) { if (Progress::check_abort()) { pbar->cleanup(); delete pbar; setError("aborted"); return(false); } pbar->increment(); } #endif return success; } /* bool SpatRaster::writeValues2(std::vector> &vals, size_t startrow, size_t nrows) { std::vector vv = flatten(vals); return writeValues(vv, startrow, nrows, 0, ncol()); } */ bool SpatRaster::writeStop(){ if (!source[0].open_write) { setError("cannot close a file that is not open"); return false; } source[0].open_write = false; bool success = true; source[0].memory = false; if (source[0].driver=="gdal") { #ifdef useGDAL success = writeStopGDAL(); //source[0].hasValues = true; #else return false; #endif } else { source[0].setRange(); //source[0].driver = "memory"; source[0].memory = true; if (source[0].values.size() > 0) { source[0].hasValues = true; } } #ifdef useRcpp if (progressbar) { pbar->increment(); pbar->cleanup(); delete pbar; } #endif return success; } #ifdef useRcpp bool SpatRaster::setValuesRcpp(Rcpp::NumericVector &v, SpatOptions &opt) { SpatRaster g = geometry(nlyr(), true, true, true); source = g.source; source[0].hasValues = true; source[0].memory = true; //source[0].names = getNames(); source[0].driver = "memory"; if (v.size() < g.size()) { std::vector vv = Rcpp::as >(v); *this = g.init(vv, opt); return (!hasError()); } else if (v.size() == g.size()) { source[0].values = Rcpp::as >(v); source[0].setRange(); } else { setError("incorrect number of values"); return false; } return true; } #endif bool SpatRaster::setValues(std::vector &v, SpatOptions &opt) { SpatRaster g = geometry(nlyr(), true, true, true); source = g.source; source[0].hasValues = true; source[0].memory = true; //source[0].names = getNames(); source[0].driver = "memory"; if (v.size() < g.size()) { *this = g.init(v, opt); return (!hasError()); } else if (v.size() == g.size()) { source[0].values = v; source[0].setRange(); } else { setError("incorrect number of values"); return false; } return true; } void SpatRaster::setRange(SpatOptions &opt) { for (size_t i=0; i(source[i].hasRange.size(), true); } } } void SpatRasterSource::setRange() { range_min.resize(nlyr); range_max.resize(nlyr); hasRange.resize(nlyr); if (nlyr==1) { minmax(values.begin(), values.end(), range_min[0], range_max[0]); hasRange[0] = true; return; } size_t nc = ncol * nrow; if (values.size() == (nc * nlyr)) { for (size_t i=0; i. #include "spatRaster.h" #include "string_utils.h" #include "file_utils.h" #include "spatTime.h" #include "recycle.h" #include "vecmath.h" #include #ifdef useGDAL #include "crs.h" #endif SpatRaster::SpatRaster(std::string fname, std::vector subds, std::vector subdsname, std::vector options) { #ifdef useGDAL constructFromFile(fname, subds, subdsname, options); #endif } SpatRaster::SpatRaster(std::vector fname, std::vector subds, std::vector subdsname, bool multi, std::vector options, std::vector x) { // argument "x" is ignored. It is only there to have four arguments such that the module // can distinguish this constructor from another with three arguments. #ifdef useGDAL if (multi) { constructFromFileMulti(fname[0], subdsname[0], x); return; } if (!constructFromFile(fname[0], subds, subdsname, options)) { setError("cannot open file: " + fname[0]); return; } SpatOptions opt; for (size_t i=1; i s) { source = s; // extent = s[0].extent; // srs = s[0].srs; } void SpatRaster::setSource(SpatRasterSource s) { s.resize(s.nlyr); std::vector vs = {s}; setSources(vs); } SpatRaster::SpatRaster(SpatRasterSource s) { std::vector vs = {s}; setSources(vs); } SpatRaster::SpatRaster() { SpatRasterSource s; s.nrow = 10; s.ncol = 10; s.extent = SpatExtent(); s.memory = true; s.filename = ""; //s.driver = ""; s.nlyr = 1; // or 0? s.resize(1); s.hasRange = { false }; s.hasValues = false; s.valueType = { 0 }; s.layers.resize(1, 0); s.datatype = ""; s.names = {"lyr.1"}; s.srs.proj4 = "+proj=longlat +datum=WGS84"; s.srs.wkt = "GEOGCRS[\"WGS 84\", DATUM[\"World Geodetic System 1984\", ELLIPSOID[\"WGS 84\",6378137,298.257223563, LENGTHUNIT[\"metre\",1]]], PRIMEM[\"Greenwich\",0, ANGLEUNIT[\"degree\",0.0174532925199433]], CS[ellipsoidal,2], AXIS[\"geodetic latitude (Lat)\",north, ORDER[1], ANGLEUNIT[\"degree\",0.0174532925199433]], AXIS[\"geodetic longitude (Lon)\",east, ORDER[2], ANGLEUNIT[\"degree\",0.0174532925199433]], USAGE[ SCOPE[\"Horizontal component of 3D system.\"], AREA[\"World.\"], BBOX[-90,-180,90,180]], ID[\"EPSG\",4326]]"; setSource(s); } /* SpatRaster SpatRaster::dropSource() { SpatRaster out = geometry(); out.source.resize(0); return out; } */ bool SpatRaster::hasValues() { // if (source.size() == 0) { // return false; // } else { return source[0].hasValues ; // } } SpatRaster::SpatRaster(std::vector rcl, std::vector ext, std::string crs) { SpatRasterSource s; s.nrow=rcl[0]; s.ncol=rcl[1]; s.extent.xmin = ext[0]; s.extent.xmax = ext[1]; s.extent.ymin = ext[2]; s.extent.ymax = ext[3]; s.hasValues = false; s.hasRange = {false}; s.valueType = { 0 }; s.memory = true; s.filename = ""; //s.driver = ""; s.nlyr = rcl[2]; s.layers.resize(1, 0); //s.layers.resize(1, s.nlyr); //std::iota(s.layers.begin(), s.layers.end(), 0); s.datatype = ""; #ifdef useGDAL std::string msg; if (!s.srs.set( crs, msg )) { setError(msg); return; } #else s.srs.proj4 = lrtrim_copy(crs); #endif for (unsigned i=0; i < rcl[2]; i++) { s.names.push_back("lyr." + std::to_string(i+1)) ; } setSource(s); } SpatRaster::SpatRaster(unsigned nr, unsigned nc, unsigned nl, SpatExtent ext, std::string crs) { SpatRasterSource s; s.nrow = nr; s.ncol = nc; s.extent = ext; s.hasValues = false; s.memory = true; s.filename = ""; //s.driver = ""; s.nlyr = nl; s.hasRange = { false }; s.valueType = { 0 }; s.layers.resize(1, 0); //s.layers.resize(1, _nlyr); //std::iota(s.layers.begin(), s.layers.end(), 0); s.datatype = ""; #ifdef useGDAL std::string msg; if (!s.srs.set(crs, msg )) { setError(msg); return; } #else s.srs.proj4 = lrtrim_copy(crs); #endif for (unsigned i=0; i < nl; i++) { s.names.push_back("lyr." + std::to_string(i+1)) ; } setSource(s); } /* SpatRaster::SpatRaster(const SpatRaster &r) { source.nrow = r.nrow; source.ncol = r.ncol; source.extent = r.extent; source.crs = r.crs; source.memory = true; nlyrs = (nlyrs < 1) ? nlyr(): nlyrs; source.resize(nlyrs); source.values.resize(0); std::vector nms(s.nlyr); for (size_t i=0; i < s.nlyr; i++) { nms[i] = "lyr" + std::to_string(i+1); } source.names = nms; // would still need "setSource" to set } */ SpatRaster SpatRaster::geometry(long nlyrs, bool properties, bool time, bool units) { SpatRasterSource s; //s.values.resize(0); s.nrow = nrow(); s.ncol = ncol(); s.extent = getExtent(); s.srs = source[0].srs; //s.prj = prj; s.memory = true; s.hasValues = false; long nl = nlyr(); bool keepnlyr = ((nlyrs == nl) || (nlyrs < 1)); nlyrs = (keepnlyr) ? nlyr(): nlyrs; if (properties) { s.hasColors = hasColors(); s.cols = getColors(); s.hasCategories = hasCategories(); s.cats = getCategories(); } s.resize(nlyrs); std::vector nms; if (keepnlyr) { nms = getNames(); if (time && hasTime()) { s.hasTime = true; s.timestep = getTimeStep(); s.time = getTime(); } if (units && hasUnit()) { s.hasUnit = true; s.unit = getUnit(); } } else { for (size_t i=0; i < s.nlyr; i++) { nms.push_back("lyr" + std::to_string(i+1)); } } s.names = nms; SpatRaster out(s); if (properties) { out.rgb = rgb; out.rgbtype = rgbtype; out.rgblyrs = rgblyrs; } return out; } SpatRaster SpatRaster::deepCopy() { return *this; } std::vector SpatRaster::resolution() { SpatExtent extent = getExtent(); return std::vector { (extent.xmax - extent.xmin) / ncol(), (extent.ymax - extent.ymin) / nrow() }; } SpatRaster SpatRaster::setResolution(double xres, double yres) { SpatRaster out; if ((xres <= 0) | (yres <= 0)) { out.setError("resolution must be larger than 0"); return(out); } SpatExtent e = getExtent(); unsigned nc = round((e.xmax-e.xmin) / xres); unsigned nr = round((e.ymax-e.ymin) / yres); double xmax = e.xmin + nc * xres; double ymax = e.ymin + nr * yres; unsigned nl = nlyr(); std::vector rcl = {nr, nc, nl}; std::vector ext = {e.xmin, xmax, e.ymin, ymax}; out = SpatRaster(rcl, ext, {""}); out.source[0].srs = source[0].srs; return out; } size_t SpatRaster::ncol() { if (source.size() > 0) { return source[0].ncol; } else { return 0; } } size_t SpatRaster::nrow() { if (source.size() > 0) { return source[0].nrow; } else { return 0; } } unsigned SpatRaster::nlyr() { unsigned x = 0; for (size_t i=0; i SpatRaster::filenames() { std::vector x(source.size()); for (size_t i=0; i SpatRaster::inMemory() { std::vector m(source.size()); for (size_t i=0; i SpatRaster::hasRange() { std::vector x; for (size_t i=0; i SpatRaster::getValueType() { std::vector d; for (size_t i=0; i 3) { return false; } for (size_t i=0; i(source[i].nlyr, d); } return true; } std::vector SpatRaster::range_min() { std::vector x; for (size_t i=0; i SpatRaster::range_max() { std::vector x; for (size_t i=0; i &tmpfs, bool unique, SpatOptions &opt) { // if a tool needs to read from disk, perhaps from unique filenames // use writeRaster to write to a single file. SpatRaster out; size_t nsrc = source.size(); std::set ufs; size_t ufsize = ufs.size(); std::string tmpbasename = tempFile(opt.get_tempdir(), opt.pid, "_temp_"); SpatOptions ops(opt); for (size_t i=0; i SpatRaster::getNames() { std::vector x; for (size_t i=0; i names, bool make_valid) { if (names.size() == 1) { recycle(names, nlyr()); } if (names.size() != nlyr()) { return false; } else { if (make_valid) { make_valid_names(names); make_unique_names(names); } size_t begin=0; size_t end; for (size_t i=0; i (names.begin() + begin, names.begin() + end); begin = end; } return true; } } std::vector SpatRaster::getLongSourceNames() { std::vector x; x.reserve(source.size()); for (size_t i=0; i names) { if (names.size() == 1) { for (size_t i=0; i SpatRaster::getSourceNames() { std::vector x; x.reserve(source.size()); for (size_t i=0; i names) { if (names.size() == 1) { for (size_t i=0; i flag) { size_t sz = source.size(); if (flag.size() == 1) recycle(flag, sz); if (flag.size() != sz) { return false; } double na = NAN; for (size_t i=0; i SpatRaster::getNAflag() { std::vector out(source.size(), NAN); for (size_t i=0; i SpatRaster::getTimeDbl() { std::vector t64 = getTime(); std::vector out(t64.size()); for (size_t i=0; i < out.size(); i++) { out[i] = t64[i]; } return out; } */ std::vector SpatRaster::getTimeStr(bool addstep) { std::vector out; std::vector time = getTime(); out.reserve(time.size()+addstep); if (addstep) out.push_back(source[0].timestep); if (source[0].timestep == "seconds") { for (size_t i=0; i < time.size(); i++) { std::vector x = get_date(time[i]); if (x.size() > 2) { out.push_back( std::to_string(x[0]) + "-" + std::to_string(x[1]) + "-" + std::to_string(x[2]) + " " + std::to_string(x[3]) + ":" + std::to_string(x[4]) + ":" + std::to_string(x[5]) ); } else { out.push_back(""); } } } else if (source[0].timestep == "days") { for (size_t i=0; i < time.size(); i++) { std::vector x = get_date(time[i]); if (x.size() > 2) { out.push_back( std::to_string(x[0]) + "-" + std::to_string(x[1]) + "-" + std::to_string(x[2]) ); } else { out.push_back(""); } } } else { for (size_t i=0; i < time.size(); i++) { out.push_back( std::to_string(time[i])); } } return out; } std::vector SpatRaster::getTime() { std::vector x; for (size_t i=0; i nas(source[i].nlyr, 0); x.insert(x.end(), nas.begin(), nas.end()); } else { x.insert(x.end(), source[i].time.begin(), source[i].time.end()); } } return(x); } std::string SpatRaster::getTimeStep() { return source[0].timestep; } bool SpatRaster::setTime(std::vector time, std::string step) { if (time.size() == 0 || step == "remove") { for (size_t i=0; i (source[i].nlyr); source[i].timestep = ""; source[i].hasTime = false; } return true; } if (time.size() != nlyr()) { return false; } if (!((step == "seconds") || (step == "raw") || (step == "days"))) { // "months", "years" return false; } size_t begin=0; for (size_t i=0; i (time.begin() + begin, time.begin() + end); source[i].timestep = step; source[i].hasTime = true; begin = end; } return true; } std::vector SpatRaster::getDepth() { std::vector x; for (size_t i=0; i nas(source[i].nlyr, NAN); x.insert(x.end(), nas.begin(), nas.end()); } else { x.insert(x.end(), source[i].depth.begin(), source[i].depth.end()); } } return(x); } bool SpatRaster::setDepth(std::vector depths) { if (depths.size() == 0) { for (size_t i=0; i(source[i].nlyr); } return true; } if (depths.size() == 1) { for (size_t i=0; i (source[i].nlyr, depths[0]); } return true; } else if (depths.size() != nlyr()) { return false; } else { size_t begin=0; for (size_t i=0; i (depths.begin() + begin, depths.begin() + end); begin = end; } return true; } } bool SpatRaster::setUnit(std::vector units) { if (units.size() == 1) { for (size_t i=0; i (source[i].nlyr, units[0]); source[i].hasUnit = true; } return true; } else if (units.size() != nlyr()) { return false; } else { size_t begin=0; for (size_t i=0; i (units.begin() + begin, units.begin() + end); source[i].hasUnit = true; begin = end; } return true; } } bool SpatRaster::hasUnit() { bool test = source[0].hasUnit; for (size_t i=1; i SpatRaster::getUnit() { std::vector x; for (size_t i=0; i nas(source[i].nlyr, ""); x.insert(x.end(), nas.begin(), nas.end()); } else { x.insert(x.end(), source[i].unit.begin(), source[i].unit.end()); } } return(x); } double SpatRaster::xres() { SpatExtent extent = getExtent(); return (extent.xmax - extent.xmin) / ncol() ; } double SpatRaster::yres() { SpatExtent extent = getExtent(); return (extent.ymax - extent.ymin) / nrow() ; } bool SpatRaster::valid_sources(bool files, bool rotated) { std::vector ff; for (size_t i=0; i SpatRaster::hasWindow() { std::vector out; out.reserve(nlyr()); for (size_t i=0; i rc(2); std::vector exp(4, 0); int_64 r = rowFromY(x.ymax - 0.5 * yr); if (r < 0) { rc[0] = 0; expand = true; exp[0] = trunc(abs(e.ymax - x.ymax) / yr); } else { rc[0] = r; } r = rowFromY(x.ymin + 0.5 * yr); if (r < 0) { expand = true; exp[1] = trunc((e.ymax - x.ymin) / yr); } r = colFromX(x.xmin + 0.5 * xr); if (r < 0) { rc[1] = 0; expand = true; exp[2] = trunc((x.xmin - e.xmin) / xres()); } else { rc[1] = r; } r = colFromX(x.xmax - 0.5 * xr); if (r < 0) { expand = true; exp[3] = trunc(abs(x.xmin - e.xmin) / xres()); } if (expand) { setError("expansion is not yet allowed"); return false; } for (size_t i=0; i lyrs; if (layer == 0) { out = x; lyrs.resize(n-1); std::iota(lyrs.begin(), lyrs.end(), 1); SpatRaster r = subset(lyrs, fopt); out.addSource(r, false, fopt); } else if (layer == n-1) { lyrs.resize(n-1); std::iota(lyrs.begin(), lyrs.end(), 0); out = subset(lyrs, fopt); out.addSource(x, false, fopt); } else { lyrs.resize(layer); std::iota(lyrs.begin(), lyrs.end(), 0); out = subset(lyrs, fopt); out.addSource(x, false, fopt); lyrs.resize(n-layer-1); std::iota(lyrs.begin(), lyrs.end(), layer+1); SpatRaster r = subset(lyrs, fopt); out.addSource(r, false, fopt); } return out; } SpatRaster SpatRaster::makeCategorical(unsigned layer, SpatOptions &opt) { if (!hasValues()) { SpatRaster out; out.setError("cannot make categries if the raster has no values"); return out; } std::vector lyrs = {layer}; SpatOptions fopt(opt); SpatRaster r = subset(lyrs, fopt); r.math2("round", 0, fopt); std::vector> u = r.unique(false, fopt); /* std::vector id(u[0].size()); std::iota(id.begin(), id.end(), 0); std::vector> rcl(2); rcl[0] = u[0]; rcl[1] = id; r = r.reclassify(rcl, true, true, true, false, false, fopt); std::vector s(id.size()); for (size_t i=0; i uu; std::vector s(u[0].size()); for (size_t i=0; i names = r.getNames(); r.setLabels(0, uu, s, names[0]); if (nlyr() == 1) { return r; } else { return replace(r, layer, opt); } } bool SpatRaster::createCategories(unsigned layer, SpatOptions &opt) { if (layer > (nlyr()-1)) { setError("invalid layer number"); return(false); } std::vector lyrs(1, layer); SpatRaster r = subset(lyrs, opt); std::vector> u = r.unique(false, opt); std::vector sl = findLyr(layer); std::vector s(u[0].size()); for (size_t i=0; i SpatRaster::hasCategories() { std::vector b(nlyr()); std::vector ns = nlyrBySource(); unsigned k = 0; for (size_t i=0; i values, std::vector labels, std::string name) { if (layer > (nlyr()-1)) { setError("invalid layer number"); return(false); } if (values.size() != labels.size()) { setError("size of values is not the same as the size of labels"); return(false); } if (values.size() == 0) { addWarning("no labels"); return(true); } std::vector sl = findLyr(layer); SpatCategories cats; cats.d.add_column(values, "value"); cats.d.add_column(labels, name); cats.index = 1; if (source[sl[0]].cats.size() <= sl[1]) { source[sl[0]].cats.resize(sl[1]+1); source[sl[0]].hasCategories.resize(sl[1]+1); } source[sl[0]].cats[sl[1]] = cats; source[sl[0]].hasCategories[sl[1]] = true; return true; } bool SpatRaster::setCategories(unsigned layer, SpatDataFrame d, unsigned index) { if (layer > (nlyr()-1)) { setError("invalid layer number"); return(false); } std::vector sl = findLyr(layer); SpatCategories cats; cats.d = d; cats.index = index; if (source[sl[0]].cats.size() < sl[1]) { source[sl[0]].cats.resize(sl[1]); } source[sl[0]].cats[sl[1]] = cats; source[sl[0]].hasCategories[sl[1]] = true; return true; } bool SpatRaster::removeCategories(unsigned layer) { if (layer > (nlyr()-1)) { setError("invalid layer number"); return(false); } std::vector sl = findLyr(layer); SpatCategories s; source[sl[0]].cats[sl[1]] = s; source[sl[0]].hasCategories[sl[1]] = false; return true; } SpatCategories SpatRaster::getLayerCategories(unsigned layer) { std::vector sl = findLyr(layer); SpatCategories cat = source[sl[0]].cats[sl[1]]; return cat; } std::vector SpatRaster::getCategories() { std::vector cats; for (size_t i=0; i SpatRaster::getLabels(unsigned layer) { std::vector out; if (layer >= nlyr()) return out; std::vector hascat = hasCategories(); if (!hascat[layer]) return out; std::vector cats = getCategories(); SpatCategories cat = cats[layer]; unsigned nc = cat.d.ncol(); if (nc == 0) return out; cat.index = cat.index > (nc-1) ? (nc-1) : cat.index; out = cat.d.as_string(cat.index); return out; } bool SpatRaster::setCatIndex(unsigned layer, unsigned index) { if (layer > (nlyr()-1)) { return(false); } std::vector sl = findLyr(layer); unsigned nc = source[sl[0]].cats[sl[1]].d.ncol(); if (index < nc) { source[sl[0]].cats[sl[1]].index = index; source[sl[0]].names[sl[1]] = source[sl[0]].cats[sl[1]].d.names[index]; return true; } else { return false; } } int SpatRaster::getCatIndex(unsigned layer) { if (layer > (nlyr()-1)) { return(-1); } std::vector sl = findLyr(layer); return source[sl[0]].cats[sl[1]].index; } std::vector SpatRaster::getColors() { std::vector cols; for (size_t i=0; i 5) { return false; } // if (cols.nrow() != 256) { // return false; // } if (layer >= nlyr()) { return false; } if (cols.ncol() == 4) { std::vector a(cols.nrow(), 255); cols.add_column(a, "alpha"); } std::vector sl = findLyr(layer); if (source[sl[0]].cols.size() < (sl[1]+1)) { source[sl[0]].cols.resize(sl[1]+1); } if (source[sl[0]].hasColors.size() < (sl[1]+1)) { source[sl[0]].hasColors.resize(sl[1]+1); } source[sl[0]].cols[sl[1]] = cols; source[sl[0]].hasColors[sl[1]] = (cols.nrow() > 1); return true; } bool SpatRaster::removeColors(size_t layer) { if (layer >= nlyr()) { return false; } std::vector sl = findLyr(layer); if (source[sl[0]].hasColors[sl[1]]) { SpatDataFrame d; source[sl[0]].cols[sl[1]] = d; source[sl[0]].hasColors[sl[1]] = false; } return true; } std::vector SpatRaster::hasColors() { std::vector b(nlyr()); std::vector ns = nlyrBySource(); unsigned k = 0; for (size_t i=0; i SpatRaster::cellFromXY (std::vector x, std::vector y) { // size of x and y should be the same size_t size = x.size(); std::vector cells(size); SpatExtent extent = getExtent(); double yr_inv = nrow() / (extent.ymax - extent.ymin); double xr_inv = ncol() / (extent.xmax - extent.xmin); for (size_t i = 0; i < size; i++) { // cannot use trunc here because trunc(-0.1) == 0 long row = std::floor((extent.ymax - y[i]) * yr_inv); // points in between rows go to the row below // except for the last row, when they must go up if (y[i] == extent.ymin) { row = nrow()-1 ; } long col = std::floor((x[i] - extent.xmin) * xr_inv); // as for rows above. Go right, except for last column if (x[i] == extent.xmax) { col = ncol() - 1 ; } long nr = nrow(); long nc = ncol(); if (row < 0 || row >= nr || col < 0 || col >= nc) { cells[i] = NAN; } else { cells[i] = row * ncol() + col; } } return cells; } double SpatRaster::cellFromXY (double x, double y) { std::vector X = {x}; std::vector Y = {y}; std::vector cell = cellFromXY(X, Y); return cell[0]; } std::vector SpatRaster::cellFromRowCol(std::vector row, std::vector col) { recycle(row, col); size_t n = row.size(); std::vector result(n); int_64 nr = nrow(); int_64 nc = ncol(); for (size_t i=0; i= nr || col[i]<0 || col[i] >= nc) ? NAN : (double)row[i] * nc + col[i]; } return result; } double SpatRaster::cellFromRowCol (int_64 row, int_64 col) { std::vector rows = {row}; std::vector cols = {col}; std::vector cell = cellFromRowCol(rows, cols); return cell[0]; } std::vector SpatRaster::cellFromRowColCombine(std::vector row, std::vector col) { size_t n = row.size(); size_t m = col.size(); double nc = ncol(); double nr = nrow(); std::vector x; x.reserve(n * m); for (size_t i=0; i= nr || col[j]<0 || col[j] >= nc) { x.push_back(NAN); } else { x.push_back(row[i] * nc + col[j]); } } } return x; } double SpatRaster::cellFromRowColCombine(int_64 row, int_64 col) { return cellFromRowCol(row, col); } std::vector SpatRaster::yFromRow(const std::vector &row) { size_t size = row.size(); std::vector result( size ); SpatExtent extent = getExtent(); double ymax = extent.ymax; double yr = yres(); int_64 nr = nrow(); for (size_t i = 0; i < size; i++) { result[i] = (row[i] < 0 || row[i] >= nr ) ? NAN : ymax - ((row[i]+0.5) * yr); } return result; } double SpatRaster::yFromRow (int_64 row) { std::vector rows = {row}; std::vector y = yFromRow(rows); return y[0]; } std::vector SpatRaster::xFromCol(const std::vector &col) { size_t size = col.size(); std::vector result( size ); SpatExtent extent = getExtent(); double xmin = extent.xmin; double xr = xres(); int_64 nc = ncol(); for (size_t i = 0; i < size; i++) { result[i] = (col[i] < 0 || col[i] >= nc ) ? NAN : xmin + ((col[i]+0.5) * xr); } return result; } double SpatRaster::xFromCol(int_64 col) { std::vector cols = {col}; std::vector x = xFromCol(cols); return x[0]; } std::vector SpatRaster::colFromX(const std::vector &x) { SpatExtent extent = getExtent(); double xmin = extent.xmin; double xmax = extent.xmax; double xr = xres(); size_t xs = x.size(); std::vector result(xs, -1); for (size_t i = 0; i < xs; i++) { if (x[i] >= xmin && x[i] < xmax ) { result[i] = trunc((x[i] - xmin) / xr); } else if (x[i] == xmax) { result[i] = ncol()-1; } } return result; } int_64 SpatRaster::colFromX(double x) { std::vector xv = {x}; return colFromX(xv)[0]; } std::vector SpatRaster::rowFromY(const std::vector &y) { SpatExtent extent = getExtent(); double ymin = extent.ymin; double ymax = extent.ymax; double yr = yres(); size_t ys = y.size(); std::vector result(ys, -1); for (size_t i = 0; i < ys; i++) { if (y[i] > ymin && y[i] <= ymax) { result[i] = trunc((ymax - y[i]) / yr); } else if (y[i] == ymin) { result[i] = nrow() - 1; } } return result; } int_64 SpatRaster::rowFromY(double y) { std::vector Y = {y}; return rowFromY(Y)[0]; } std::vector> SpatRaster::xyFromCell( std::vector &cell) { size_t n = cell.size(); SpatExtent extent = getExtent(); double xmin = extent.xmin; double ymax = extent.ymax; double yr = yres(); double xr = xres(); double ncells = ncell(); size_t nc = ncol(); std::vector< std::vector > out(2, std::vector (n, NAN) ); for (size_t i = 0; i= ncells)) continue; size_t row = cell[i] / nc; size_t col = cell[i] - (row * nc); out[0][i] = xmin + (col + 0.5) * xr; out[1][i] = ymax - (row + 0.5) * yr; } return out; } std::vector< std::vector> SpatRaster::xyFromCell( double cell) { std::vector vcell = {cell}; return xyFromCell(vcell); } std::vector> SpatRaster::rowColFromCell(std::vector &cell) { size_t cs = cell.size(); std::vector> result(2, std::vector (cs, -1) ); double nc = ncell(); for (size_t i = 0; i < cs; i++) { if ((cell[i] >= 0) && (cell[i] < nc )) { result[0][i] = trunc(cell[i]/ ncol()); result[1][i] = (cell[i] - ((result[0][i]) * ncol())); } } return result; } std::vector> SpatRaster::rowColFromExtent(SpatExtent e) { std::vector> xy = e.asPoints(); std::vector col = colFromX(xy[0]); std::vector row = rowFromY(xy[1]); std::vector> out = { row, col }; return out; } std::vector SpatRaster::adjacentMat(std::vector cells, std::vector mat, std::vector dim, bool include) { std::vector out; if ((dim.size() != 2) || (dim[0] % 2 == 0) || (dim[1] %2 == 0)) { setError("invalid matrix dimensions (must be odd sized)"); return out; } if ((dim[0] == 1) && (dim[1] == 1)) { setError("invalid matrix dimensions (too small)"); return out; } int dy = dim[0] / 2; int dx = dim[1] / 2; unsigned n = cells.size(); int nngb = std::accumulate(mat.begin(), mat.end(), 0); out.reserve(n * (nngb + include)); std::vector offcols(nngb); std::vector offrows(nngb); size_t i = 0; size_t j = 0; for (int r = -dy; r<=dy; r++) { for (int c = -dx; c<=dx; c++) { if (mat[i]) { offrows[j] = r; offcols[j] = c; j++; } i++; } } bool globlatlon = is_global_lonlat(); std::vector> rc = rowColFromCell(cells); std::vector r = rc[0]; std::vector c = rc[1]; std::vector cols(nngb); std::vector rows(nngb); int_64 nc = ncol(); int_64 lc = nc-1; for (size_t i=0; i lc) cols[j] = cols[j] - nc; } } std::vector adjcells = cellFromRowCol(rows, cols); if (include) { out.push_back(cells[i]); } out.insert(out.end(), adjcells.begin(), adjcells.end()); } return out; } std::vector SpatRaster::adjacent(std::vector cells, std::string directions, bool include) { std::vector out; std::vector f {"rook", "queen", "bishop", "4", "8", "16"}; if (std::find(f.begin(), f.end(), directions) == f.end()) { setError("argument directions is not valid"); return(out); } unsigned n = cells.size(); unsigned nngb = (directions=="queen" || directions=="8") ? 8 : (directions=="16" ? 16 : 4); nngb += include; out.reserve(n * nngb); std::vector> rc = rowColFromCell(cells); std::vector r = rc[0]; std::vector c = rc[1]; bool globlatlon = is_global_lonlat(); int_64 nc = ncol(); int_64 lc = nc-1; std::vector cols, rows; if (directions == "rook" || directions == "4") { for (size_t i=0; i adjcells = cellFromRowCol(rows, cols); out.insert(out.end(), adjcells.begin(), adjcells.end()); } } else if (directions == "queen" || directions == "8") { for (size_t i=0; i adjcells = cellFromRowCol(rows, cols); out.insert(out.end(), adjcells.begin(), adjcells.end()); } } else if (directions == "bishop") { for (size_t i=0; i adjcells = cellFromRowCol(rows, cols); out.insert(out.end(), adjcells.begin(), adjcells.end()); } } else if (directions == "16") { for (size_t i=0; i lc) ? cols[j]-nc : cols[j]; } } } if (include) { out.push_back(cells[i]); } std::vector adjcells = cellFromRowCol(rows, cols); out.insert(out.end(), adjcells.begin(), adjcells.end()); } } return(out); } SpatVector SpatRaster::as_points(bool values, bool narm, SpatOptions &opt) { BlockSize bs = getBlockSize(opt); std::vector v, vout; vout.reserve(v.size()); SpatVector pv; SpatGeom g; g.gtype = points; std::vector> xy; if ((!values) && (!narm)) { double nc = ncell(); for (size_t i=0; i nms = getNames(); for (size_t i=0; i(v.begin()+off2, v.begin()+off2+vnc); } } } readStop(); pv.srs = source[0].srs; return(pv); } void getCorners(std::vector &x, std::vector &y, const double &X, const double &Y, const double &xr, const double &yr) { x[0] = X - xr; y[0] = Y - yr; x[1] = X - xr; y[1] = Y + yr; x[2] = X + xr; y[2] = Y + yr; x[3] = X + xr; y[3] = Y - yr; x[4] = x[0]; y[4] = y[0]; } /* SpatVector SpatRaster::as_polygons(bool values, bool narm) { if (!values) narm=false; SpatVector v; SpatGeom g; g.gtype = polygons; double xr = xres()/2; double yr = yres()/2; std::vector x(5); std::vector y(5); if (!values) { std::vector cells(ncell()) ; std::iota (std::begin(cells), std::end(cells), 0); std::vector< std::vector > xy = xyFromCell(cells); for (size_t i=0; i > att(ncell(), std::vector (nl)); BlockSize bs = getBlockSize(4); std::vector< std::vector > xy; std::vector atts(nl); for (size_t i=0; i vals = readBlock(out.bs, i); unsigned nc=out.bs.nrows[i] * ncol(); for (size_t j=0; j nms = getNames(); for (size_t i=0; i 1000000) { // for testing with canPIM=false vect.setError("the raster is too large"); return vect; } } bool remove_values = false; if (narm) { if (!values) remove_values = true; values=true; } unsigned nl = nlyr(); unsigned nc = ncell(); if (values) { std::vector v = getValues(-1, opt); std::vector nms = getNames(); make_unique_names(nms); for (size_t i=0; i vv(v.begin()+offset, v.begin()+offset+nc); vect.add_column(vv, nms[i]); } } SpatGeom g; g.gtype = polygons; double xr = xres()/2; double yr = yres()/2; std::vector x(5); std::vector y(5); std::vector cells(ncell()) ; std::iota (std::begin(cells), std::end(cells), 0); std::vector< std::vector > xy = xyFromCell(cells); for (int i=nc-1; i>=0; i--) { if (narm) { bool erase = false; for (size_t j=0; j 1000000) { // for testing with canPIM=false vect.setError("the raster is too large"); return vect; } } SpatGeom g; g.gtype = lines; std::vector cols(ncol()); std::vector rows(nrow()); std::iota(std::begin(rows), std::end(rows), 0); std::iota(std::begin(cols), std::end(cols), 0); std::vector x = xFromCol(cols); std::vector y = yFromRow(rows); double xr = xres()/2; double yr = yres()/2; for (double &d : x) d = d - xr; for (double &d : y) d = d + yr; x.push_back(x[x.size()-1] + xres()); y.push_back(y[y.size()-1] - yres()); SpatExtent e = getExtent(); for (size_t i=0; i xc = {x[i], x[i]}; std::vector yc = {e.ymin, e.ymax}; SpatPart p(xc, yc); g.addPart(p); vect.addGeom(g); g.parts.resize(0); } for (size_t i=0; i xc = {e.xmin, e.xmax}; std::vector yc = {y[i], y[i]}; SpatPart p(xc, yc); g.addPart(p); vect.addGeom(g); g.parts.resize(0); } vect.srs = source[0].srs; return(vect); } bool SpatRaster::setRGB(int r, int g, int b, int alpha, std::string type) { std::vector channels; if (alpha >= 0) { channels = {r, g, b, alpha}; } else { channels = {r, g, b}; } size_t mxlyr = vmax( channels, false ); if (nlyr() <= mxlyr) { //addWarning("layer number for R, G, B, cannot exceed the number of layers"); return false; } else { size_t mnlyr = vmin( channels, false );; if (mnlyr >= 0) { rgblyrs = channels; rgbtype = type; // check validity rgb = true; } else { rgb = false; return false; } } return true; } std::vector SpatRaster::getRGB(){ return rgblyrs; } void SpatRaster::removeRGB(){ rgblyrs = std::vector(0); rgb = false; } bool SpatRaster::to_memory(SpatOptions &opt) { if ((nsrc() == 1) & (source[0].memory)) { return true; } SpatRaster g = geometry(); SpatRasterSource s = g.source[0]; s.hasValues = true; s.memory = true; s.names = getNames(); s.driver = "memory"; source[0].values = getValues(-1, opt); return true; } SpatRaster SpatRaster::to_memory_copy(SpatOptions &opt) { SpatRaster m = geometry(); std::vector v = getValues(-1, opt); m.setValues(v, opt); return m; } std::vector SpatRaster::getFileBlocksize() { std::vector b; for (size_t i=0; i #include #include #include #include bool write_text(std::string filename, std::vector s) { std::ofstream f; f.open(filename); if (f.is_open()) { for (size_t i=0; i read_text(std::string filename) { std::vector s; std::string line; std::ifstream f(filename); if (f.is_open()) { while (getline(f, line)) { if (line.empty()) { s.push_back(""); } else { s.push_back(line); } } f.close(); } return s; } std::string getFileExt(const std::string& s) { size_t i = s.rfind('.', s.length()); if (i != std::string::npos) { return(s.substr(i, s.length() - i)); } return(""); } std::string setFileExt(const std::string& s, const std::string& ext) { size_t i = s.rfind('.', s.length()); if (i != std::string::npos) { return(s.substr(0, i) + ext); } return(s + ext); } std::string noext(std::string filename) { const size_t p = filename.rfind('.'); if (std::string::npos != p) { filename.erase(p); } return filename; } std::string basename(std::string filename) { const size_t i = filename.find_last_of("\\/"); if (std::string::npos != i) { filename.erase(0, i + 1); } return filename; } std::string basename_noext(std::string filename) { filename = basename(filename); filename = noext(filename); return filename; } std::string dirname(std::string filename) { const size_t i = filename.find_last_of("\\/"); if (std::string::npos != i) { return( filename.substr(0, i) ); } else { return (""); } } bool file_exists(const std::string& name) { std::ifstream f(name.c_str()); return f.good(); } bool path_exists(std::string path) { struct stat info; stat(path.c_str(), &info ); if(info.st_mode & S_IFDIR) { return true; } return false; } bool canWrite(std::string filename) { FILE *fp = fopen(filename.c_str(), "w"); if (fp == NULL) { return false; } fclose(fp); remove(filename.c_str()); return true; } std::string get_path(const std::string filename) { size_t found = filename.find_last_of("/\\"); std::string result = filename.substr(0, found); return result; } bool filepath_exists(const std::string& name) { std::string p = get_path(name); return path_exists(p); } bool can_write(std::string filename, bool overwrite, std::string &msg) { if (file_exists(filename)) { if (overwrite) { if (remove(filename.c_str()) != 0) { msg = ("cannot overwrite existing file"); return false; } //std::string aux = filename + ".aux.xml"; //remove(aux.c_str()); std::vector exts = {".vat.dbf", ".vat.cpg", ".json"}; for (size_t i=0; i characters = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K', 'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m', 'n','o','p','q','r','s','t','u','v','w','x','y','z' }; std::default_random_engine generator(std::random_device{}()); double seed = std::chrono::system_clock::now().time_since_epoch().count(); generator.seed(seed); std::uniform_int_distribution<> distrib(0, characters.size()-1); auto draw = [ characters, &distrib, &generator ]() { return characters[ distrib(generator) ]; }; std::string filename(15, 0); std::generate_n(filename.begin(), 15, draw); filename = tmpdir + "/spat_" + filename + "_" + std::to_string(pid) + ext; return filename; } terra/src/file_utils.h0000644000175000017500000000131014201035750014610 0ustar nileshnilesh#ifndef FILEUTILS_GUARD #define FILEUTILS_GUARD bool file_exists(const std::string& name); bool filepath_exists(const std::string& name); bool can_write(std::string filename, bool overwrite, std::string &msg); std::string getFileExt(const std::string& s); std::string setFileExt(const std::string& s, const std::string& ext); std::string basename(std::string filename); std::string basename_noext(std::string filename); std::string noext(std::string filename); std::string tempFile(std::string tmpdir, unsigned pid, std::string ext); std::string dirname(std::string filename); bool write_text(std::string filename, std::vector s); std::vector read_text(std::string filename); #endif terra/src/sample.cpp0000644000175000017500000005423114201035750014277 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include #include "spatRaster.h" #include "distance.h" #include "recycle.h" #include #include #include "string_utils.h" void getSampleRowCol(std::vector &oldrow, std::vector &oldcol, size_t nrows, size_t ncols, size_t snrow, size_t sncol) { double rf = nrows / (double)(snrow); double cf = ncols / (double)(sncol); //double rstart = std::floor(0.5 * rf); //double cstart = std::floor(0.5 * cf); double rstart = 0.5 * rf; double cstart = 0.5 * cf; oldcol.reserve(sncol); for (size_t i =0; i SpatRaster::readSample(unsigned src, size_t srows, size_t scols) { unsigned nl = source[src].nlyr; std::vector oldcol, oldrow; std::vector out; getSampleRowCol(oldrow, oldcol, nrow(), ncol(), srows, scols); out.reserve(srows*scols); if (source[src].hasWindow) { size_t offrow = source[src].window.off_row; size_t offcol = source[src].window.off_col; size_t fncol = source[src].window.full_ncol; size_t oldnc = fncol * source[src].window.full_nrow; for (size_t lyr=0; lyr= ncell())) { return( *this ); } double f = std::min(1.0, sqrt(size / ncell())); size_t nr = std::min((size_t)ceil(nrow() * f), nrow()); size_t nc = std::min((size_t)ceil(ncol() * f), ncol()); if ((nc == ncol()) && (nr == nrow())) { return( *this ); } SpatRaster out = geometry(nlyr(), true); out.source[0].nrow = nr; out.source[0].ncol = nc; if (!source[0].hasValues) return (out); std::vector v; for (size_t src=0; src 0"); } nr = std::min(nr, nrow()); nc = std::min(nc, ncol()); if ((nc == ncol()) && (nr == nrow())) { return( *this ); } out.source[0].nrow = nr; out.source[0].ncol = nc; if (!source[0].hasValues) return (out); std::vector v; for (size_t src=0; src> SpatRaster::sampleRegularValues(unsigned size, SpatOptions &opt) { std::vector> out; if (!source[0].hasValues) return (out); size_t nsize; size_t nr = nrow(); size_t nc = ncol(); if (size < ncell()) { double f = sqrt(size / ncell()); nr = std::ceil(nrow() * f); nc = std::ceil(ncol() * f); } nsize = nc * nr; std::vector v; if ((size >= ncell()) || ((nc == ncol()) && (nr == nrow()))) { v = getValues(-1, opt) ; if (hasError()) return out; for (size_t i=0; i vv(v.begin()+offset, v.begin()+offset+nsize); out.push_back(vv); } return out; } for (size_t src=0; src vv(v.begin()+offset, v.begin()+offset+nsize); out.push_back(vv); } } return out; } std::vector> SpatRaster::sampleRowColValues(size_t nr, size_t nc, SpatOptions &opt) { std::vector> out; if (!source[0].hasValues) return (out); if ((nr == 0) || (nc ==0)) { return(out); } nr = std::min(nr, nrow()); nc = std::min(nc, ncol()); size_t nsize = nc * nr; std::vector v; if ((nc == ncol()) && (nr == nrow())) { v = getValues(-1, opt) ; if (hasError()) return out; for (size_t i=0; i vv(v.begin()+offset, v.begin()+offset+nsize); out.push_back(vv); } return out; } for (size_t src=0; src vv(v.begin()+offset, v.begin()+offset+nsize); out.push_back(vv); } } return out; } std::vector sample_replace(size_t size, size_t N, unsigned seed){ std::default_random_engine gen(seed); std::uniform_int_distribution<> U(0, N-1); std::vector sample; sample.reserve(size); for (size_t i=0; i sample_replace_weights(size_t size, size_t N, std::vector prob, unsigned seed){ // normalize prob double maxw = *max_element(prob.begin(), prob.end()); for (double& d : prob) d /= maxw; double minw = *min_element(prob.begin(), prob.end()); std::default_random_engine gen(seed); std::uniform_int_distribution<> U(0, N-1); std::vector sample; sample.reserve(size); std::uniform_real_distribution<> Uw(minw, 1); size_t cnt = 0; size_t cnt2 = 0; size_t ssize = size * 10; while (cnt < size) { double w = Uw(gen); double v = U(gen); if (prob[v] >= w) { sample.push_back(v); cnt++; } else { cnt2++; if (cnt2 > ssize) cnt = size; } } return sample; } /* std::vector sample_replace_weights_gen(size_t size, size_t N, std::vector prob, std::default_random_engine gen){ // normalize prob double minw = *min_element(prob.begin(),prob.end()); double maxw = *max_element(prob.begin(),prob.end()) - minw; for (double& d : prob) d = (d - minw) / maxw; std::uniform_int_distribution<> U(0, N-1); std::vector sample; sample.reserve(size); std::uniform_real_distribution<> Uw(0, 1); size_t cnt = 0; while (cnt < size) { double w = Uw(gen); double v = U(gen); if (prob[v] >= w) { sample.push_back(v); cnt++; } } return sample; } */ std::vector sample_no_replace(size_t size, size_t N, unsigned seed){ size_t one = 1; size = std::max(one, std::min(size, N)); std::vector sample; if (size == N) { sample.resize(size); std::iota(sample.begin(), sample.end(), 0); return sample; } std::default_random_engine gen(seed); if (size >= .66 * N) { sample.resize(N); std::iota(std::begin(sample), std::end(sample), 0); std::shuffle(sample.begin(), sample.end(), gen); if (size < N) { sample.erase(sample.begin()+size, sample.end()); } return sample; } std::uniform_real_distribution<> U( 0, std::nextafter(1.0, std::numeric_limits::max() ) ); sample.reserve(size); for (size_t i=0; i sample_no_replace_weights(size_t size, size_t N, std::vector prob, unsigned seed){ size_t one = 1; size = std::max(one, std::min(size, N)); std::vector sample; std::default_random_engine gen(seed); if (size == N) { sample.resize(size); std::iota(sample.begin(), sample.end(), 0); std::shuffle(sample.begin(), sample.end(), gen); return sample; } std::uniform_int_distribution<> U(0, std::numeric_limits::max()); std::unordered_set sampleset; size_t isize = size; if (size > (0.8 * N)) { isize = N - size; for (double &d : prob) d = 1-d; size_t ssize = isize * (1.1 + isize / N); size_t cnt=0; while (sampleset.size() < isize) { seed = U(gen); std::vector s = sample_replace_weights(ssize, N, prob, seed); for (size_t i=0; i 10) break; } std::vector invsamp; invsamp.insert(invsamp.begin(), sampleset.begin(), sampleset.end()); std::sort(invsamp.begin(), invsamp.end()); invsamp.push_back(N+1); size_t j=0; sample.reserve(size); for (size_t i=0; i s = sample_replace_weights(ssize, N, prob, seed); for (size_t i=0; i 10) break; } sample.insert(sample.begin(), sampleset.begin(), sampleset.end()); if (sample.size() > size) { sample.resize(size); }; } return(sample); } std::vector sample(size_t size, size_t N, bool replace, std::vector prob, unsigned seed){ if ((size == 0) || (N == 0)) { std::vector s; return s; } bool w = prob.size() == N; if (replace) { if (N == 1) { std::vector s(size,0); return s; } if (w) { return sample_replace_weights(size, N, prob, seed); } else { return sample_replace(size, N, seed); } } else { if (N == 1) { std::vector s(1,0); return s; } if (w) { return sample_no_replace_weights(size, N, prob, seed); } else { return sample_no_replace(size, N, seed); } } } std::vector> SpatRaster::sampleRandomValues(unsigned size, bool replace, unsigned seed) { double nc = ncell(); std::vector cells; std::vector w; if (replace) { cells = sample(size, nc, false, w, seed); } else { cells = sample(size, nc, true, w, seed); } std::vector dcells(cells.begin(), cells.end()); std::vector> d = extractCell(dcells); return d; } SpatRaster SpatRaster::sampleRandomRaster(unsigned size, bool replace, unsigned seed) { unsigned nsize; unsigned nr = nrow(); unsigned nc = ncol(); if (size < ncell()) { double f = sqrt(size / ncell()); nr = std::ceil(nrow() * f); nc = std::ceil(ncol() * f); } SpatRaster out = geometry(nlyr(), true); out.source[0].nrow = nr; out.source[0].ncol = nc; if (!source[0].hasValues) return (out); nsize = nr * nc; std::vector> vv = sampleRandomValues(nsize, replace, seed); for (size_t i=0; i SpatExtent::test_sample(size_t size, size_t N, bool replace, std::vector w, unsigned seed) { return sample(size, N, replace, w, seed); } std::vector> SpatExtent::sampleRandom(size_t size, bool lonlat, unsigned seed){ std::vector> out(2); if (size == 0) return out; std::default_random_engine gen(seed); if (lonlat) { double d = (ymax - ymin) / 1000.0; std::vector r = seq(ymin, ymax, d); std::vector w; w.reserve(r.size()); for (size_t i=0; i x = sample(size, r.size(), true, w, seed); std::vector lat, lon; lat.reserve(size); lon.reserve(size); std::uniform_real_distribution<> U1(-0.5, 0.5); double dx = 0.5 * d; for (size_t i=0; i U2(xmin, xmax); for (size_t i=0; i x, y; x.reserve(size); y.reserve(size); std::uniform_real_distribution<> runifx(xmin, xmax); std::uniform_real_distribution<> runify(ymin, ymax); for (size_t i=0; i> SpatExtent::sampleRegular(size_t size, bool lonlat) { std::vector> out(2); if (size == 0) return out; double r1 = xmax - xmin; double r2 = ymax - ymin; if (lonlat) { double halfy = ymin + (ymax - ymin)/2; double dx = distance_lonlat(xmin, halfy, xmax, halfy); double dy = distance_lonlat(0, ymin, 0, ymax); double ratio = dx/dy; double ny = std::max(1.0, sqrt(size / ratio)); double nx = std::max(1.0, size / ny); ny = std::round(ny); nx = std::round(nx); double x_i = r1 / nx; double y_i = r2 / ny; std::vector lat, lon, w, xi; lat.reserve(ny); lat.push_back(ymin+0.5*y_i); for (size_t i=1; i x; if (start < xmin) { x = { halfx }; } else { while (start > xmin) { start -= xi[i]; } x = seq(start + xi[i], xmax, xi[i]); } if (x.size() <= 1) { x = { halfx }; } std::vector y(x.size(), lat[i]); out[0].insert(out[0].end(), x.begin(), x.end()); out[1].insert(out[1].end(), y.begin(), y.end()); } } else { double ratio = r1/r2; double ny = std::max(1.0, sqrt(size / ratio)); double nx = std::max(1.0, size / ny); ny = std::round(ny); nx = std::round(nx); double x_i = r1 / nx; double y_i = r2 / ny; std::vector x, y; x.reserve(nx); y.reserve(ny); x.push_back(xmin+0.5*x_i); for (size_t i=1; i SpatRaster::sampleCells(unsigned size, std::string method, bool replace, unsigned seed) { std::default_random_engine gen(seed); std::vector out; if ((size >= ncell()) & (!replace)) { out.resize(ncell()); std::iota(out.begin(), out.end(), 0); if (method == "random") { std::shuffle(out.begin(), out.end(), gen); } return out; } if (method == "random") { } else if (method == "regular") { } else { //method == "stratified" } // else "Cluster" return out; } SpatVector SpatVector::sample(unsigned n, std::string method, unsigned seed) { std::string gt = type(); SpatVector out; if (gt != "polygons") { out.setError("only implemented for polygons"); return out; } if (n == 0) { out.srs = srs; return out; } /* if (strata != "") { // should use // SpatVector a = aggregate(strata, false); // but get nasty self-intersection precision probs. int i = where_in_vector(strata, get_names()); if (i < 0) { out.setError("cannot find field"); return out; } SpatDataFrame uv; std::vector idx = df.getIndex(i, uv); for (size_t i=0; i g; g.resize(0); for (size_t j=0; j a = area("m", true, {}); if (hasError()) { out.setError(getError()); return out; } double suma = accumulate(a.begin(), a.end(), 0.0); /* if (by_geom) { std::vector pa; pa.reserve(a.size()); for (size_t i=0; i> pxy(2); std::vector nsamp(size()); for (size_t i=0; i 0) { SpatGeom g = getGeom(i); SpatVector ve(g.extent, ""); ve.srs = srs; double vea = ve.area()[0]; if (random) { double m = vea / a[i]; m = std::max(2.0, std::min(m*m, 100.0)); size_t ssize = pa[i] * n * m; pxy = g.extent.sampleRandom(ssize, lonlat, seed); } else { size_t ssize = std::round(pa[i] * n * vea / a[i]); pxy = g.extent.sampleRegular(ssize, lonlat); } SpatVector vpnt(pxy[0], pxy[1], points, ""); SpatVector vpol(g); vpnt = vpnt.intersect(vpol); if (random) { size_t psize = pa[i] * n; if (vpnt.size() > psize) { std::vector rows(psize); std::iota(rows.begin(), rows.end(), 0); vpnt = vpnt.subset_rows(rows); } } nsamp[i] = vpnt.size(); if (out.size() == 0) { out = vpnt; } else { out = out.append(vpnt, true); } } } std::vector id(size()); std::iota(id.begin(), id.end(), 1); rep_each_vect(id, nsamp); SpatDataFrame df; df.add_column(id, "pol.id"); out.df = df; } else { */ std::vector> pxy(2); SpatVector ve(extent, ""); ve.srs = srs; double vea = ve.area("m", true, {})[0]; if (random) { double m = vea / suma; // the larger the sample size, the fewer extra samples needed double smx = sqrt(std::max(9.0, 100.0 - n)); m = std::max(smx, std::min(m*m, 100.0)); size_t ssize = n * m; pxy = extent.sampleRandom(ssize, lonlat, seed); } else { size_t ssize = std::round(n * vea / suma); pxy = extent.sampleRegular(ssize, lonlat); } out = SpatVector(pxy[0], pxy[1], points, ""); out = intersect(out); if (random) { if (out.size() > n) { std::vector rows(out.size()); std::iota(rows.begin(), rows.end(), 0); std::default_random_engine gen(seed); std::shuffle(rows.begin(), rows.end(), gen); rows.resize(n); out = out.subset_rows(rows); } } //std::vector id(out.size(), 1); //SpatDataFrame df; //df.add_column(id, "pol.id"); //out.df = df; // } out.srs = srs; return out; } SpatVector SpatVector::sample_geom(std::vector n, std::string method, unsigned seed) { SpatVector out; if (n.size() != size()) { out.setError("length of samples does not match number of geoms"); return out; } if (n.size() == 0) { out.srs = srs; return out; } for (size_t i=0; i sample(size_t size, size_t N, bool replace, std::vector prob, unsigned seed){ // Sample "size" elements from [1, N] std::vector result; std::default_random_engine gen(seed); bool weights = false; if (prob.size() == N) { weights = true; // should check for neg numbers double minw = *min_element(prob.begin(),prob.end()); double maxw = *max_element(prob.begin(),prob.end()) - minw; for (double& d : prob) d = (d - minw) / maxw; } if (replace) { //std::vector samples; result.reserve(size); std::uniform_int_distribution<> distribution(0, N-1); if (weights) { std::uniform_real_distribution<> wdist(0, 1); size_t cnt = 0; while (cnt < size) { double w = wdist(gen); double v = distribution(gen); if (prob[v] >= w) { result.push_back(v); cnt++; } } } else { for (size_t i=0; i distribution(1, N); std::unordered_set samples; if (weights) { std::uniform_int_distribution<> wdist(0, N-1); size_t cnt = 0; size_t r = 0; while (cnt < size) { double w = wdist(gen)/N; double v = distribution(gen); if (prob[v] >= w) { if (!samples.insert(v).second) { samples.insert(r); cnt++; } } r++; r = r%(N-1); } } else { for (size_t r = N - size; r < N; ++r) { unsigned v = distribution(gen) - 1; if (!samples.insert(v).second) samples.insert(r); } } result = std::vector(samples.begin(), samples.end()); std::shuffle(result.begin(), result.end(), gen); } return result; } */ terra/src/Makevars.in0000644000175000017500000000007614201035750014411 0ustar nileshnileshPKG_CPPFLAGS=@PKG_CPPFLAGS@ PKG_LIBS=@PKG_LIBS@ CXX_STD=CXX11 terra/src/Makevars.ucrt0000644000175000017500000000141014202616760014760 0ustar nileshnileshTARGET = lib$(subst gcc,,$(COMPILED_BY))$(R_ARCH) PKG_LIBS = \ -lgdal -lgta -lsqlite3 -lmysqlclient -lspatialite -lproj -lgeos_c -lgeos \ -ljson-c -lnetcdf -lpq \ -lwebp -lcurl -lidn2 -lunistring -lssh2 -lgcrypt -lgpg-error -lssl \ -lhdf5_hl -lhdf5 -lexpat -lfreexl \ -lmfhdf -ldf -lportablexdr -lpcre \ -lopenjp2 -ljasper -lpng -ljpeg -ltiff -lwebp -lgeotiff -lgif -lxml2 -llzma \ -lodbc32 -lodbccp32 -liconv -lpsapi -lwldap32 -lsecur32 -lgdi32 -lnormaliz \ -lbz2 -lzstd -lz -lcrypto -lcrypt32 -lcfitsio -lws2_32 CXX_STD = CXX11 all: clean winlibs clean: rm -f $(SHLIB) $(OBJECTS) winlibs: cp -r $(R_TOOLS_SOFT)/share/gdal ../inst/ cp -r $(R_TOOLS_SOFT)/share/proj ../inst/ .PHONY: all winlibs clean terra/src/vecmath.h0000644000175000017500000003155214201035750014113 0ustar nileshnilesh// Copyright (c) 2018-2020 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #ifndef VECMATH_GUARD #define VECMATH_GUARD #include #include #include #include #include "NA.h" #include bool haveFun(std::string fun); std::function&, bool)> getFun(std::string fun); bool bany(const std::vector& v); bool ball(const std::vector& v); template std::vector flatten(const std::vector>& v) { std::size_t total_size = 0; for (const auto& sub : v) total_size += sub.size(); std::vector result; result.reserve(total_size); for (const auto& sub : v) result.insert(result.end(), sub.begin(), sub.end()); return result; } static inline double interpolate(double x, double y1, double y2, unsigned x1, unsigned x2) { double denom = (x2-x1); return y1 + (x-x1) * (y2-y1)/denom; } static inline std::vector vquantile(std::vector v, const std::vector& probs, bool narm) { size_t n = v.size(); if (n==0) { return std::vector(probs.size(), NAN); } if (n == 1) { return std::vector(probs.size(), v[0]); } //na_omit(v); v.erase(std::remove_if(std::begin(v), std::end(v), [](const double& value) { return std::isnan(value); }), std::end(v)); if (((!narm) && (v.size() < n)) || (v.size() == 0)) { return std::vector(probs.size(), NAN); } n = v.size(); std::sort(v.begin(), v.end()); size_t pn = probs.size(); std::vector q(pn); for (size_t i = 0; i < pn; ++i) { double x = probs[i] * (n-1); unsigned x1 = std::floor(x); unsigned x2 = std::ceil(x); if (x1 == x2) { q[i] = v[x1]; } else { q[i] = interpolate(x, v[x1], v[x2], x1, x2); } } return q; } template std::vector vunique(std::vector d) { std::sort(d.begin(), d.end()); d.erase(std::unique(d.begin(), d.end()), d.end()); return d; } template std::vector vtostring(std::vector& v) { std::vector s; std::transform(std::begin(v), std::end(v), std::back_inserter(s), [](double d) { return std::to_string(d); } ); return s; } template T vmedian(std::vector& v, bool narm) { size_t n = v.size(); std::vector vv; vv.reserve(n); for (size_t i=0; i::value; } } n = vv.size(); if (n == 0) { return(NA::value); } if (n == 1) { return(vv[0]); } size_t n2 = n / 2; std::nth_element(vv.begin(), vv.begin()+n2, vv.end()); if (n % 2) { return vv[n2]; } else { return (vv[n2] + vv[n2-1]) / 2; } } template T vsum(std::vector& v, bool narm) { T x = v[0]; if (narm) { for (size_t i=1; i::value; break; } else { x += v[i]; } } } } return x; } template T vsum2(std::vector& v, bool narm) { T x = v[0] * v[0]; if (narm) { for (size_t i=1; i::value; break; } else { x += v[i] * v[i]; } } } } return x; } template T vprod(std::vector& v, bool narm) { T x = v[0]; if (narm) { for (size_t i=1; i::value; break; } else { x *= v[i]; } } } } return x; } template double vmean(std::vector& v, bool narm) { double x = 0; unsigned d = 0; if (narm) { for (size_t i=0; i 0) { x /= d; } else { x = NAN; } return x; } template double vsd(std::vector& v, bool narm) { double m = vmean(v, narm); if (std::isnan(m)) return m; double x = 0; size_t n = 0; for (size_t i=0; i double vsdpop(std::vector& v, bool narm) { double m = vmean(v, narm); if (std::isnan(m)) return m; double x = v[0]; size_t n = 0; for (size_t i=0; i T vmin(std::vector& v, bool narm) { T x = v[0]; if (narm) { for (size_t i=1; i::value; } else { x = std::min(x, v[i]); } } } return x; } template T vfirst(std::vector& v, bool narm) { if (narm) { for (size_t i=0; i T vmax(std::vector& v, bool narm) { T x = v[0]; if (narm) { for (size_t i=1; i::value; } else { x = std::max(x, v[i]); } } } return x; } template double vwhich(const std::vector& v, bool narm) { double out; for (size_t i=0; i T vwhichmin(const std::vector& v, bool narm) { T x = v[0]; T out; if (is_NA(x)) { out = NA::value; } else { out = 0; } if (narm) { for (size_t i=1; i::value; } else { if (v[i] < x) { x = v[i]; out = i; } } } } if (is_NA(out)) { return out; } else { return (out + 1); // +1 for R } } template T vwhichmax(const std::vector& v, bool narm) { T x = v[0]; T out; if (is_NA(x)) { out = NA::value; } else { out = 0; } if (narm) { for (size_t i=1; i x) { x = v[i]; out = i; } } } } else { if (is_NA(x)) { return out; } for (size_t i=0; i::value; } else { if (v[i] > x) { x = v[i]; out = i; } } } } if (is_NA(out)) { return out; } else { return (out + 1); // +1 for R } } // problematic; should be ok for int and float but // won't work with bool values (nodata == 0) template T vall(const std::vector& v, bool narm) { T x; if (narm) { x = 1; for (size_t i=0; i::value : x; } else { x = 1; for (size_t i=0; i T vany(const std::vector& v, bool narm) { T x = 0; bool hasnd = false; for (size_t i=0; i::value;; } return x; } template std::vector vrange(std::vector& v, bool narm) { std::vector x = { v[0], v[0] }; if (narm) { for (size_t i=1; i::value; x[1] = NA::value; } else { x[0] = std::min(x[0], v[i]); x[1] = std::max(x[1], v[i]); } } } } return x; } template T vmodal(std::vector& v, bool narm) { size_t n = v.size(); std::vector counts(n, 0); std::sort(v.begin(), v.end()); for (size_t i = 0; i < n; ++i) { counts[i] = 0; size_t j = 0; while ((j < i) && (v[i] != v[j])) { ++j; } ++(counts[j]); } size_t maxCount = 0; for (size_t i = 1; i < n; ++i) { if (counts[i] > counts[maxCount]) { maxCount = i; } } return v[maxCount]; } template std::vector visna(std::vector& v) { std::vector x(v.size(), false); for (size_t i=0; i std::vector visnotna(std::vector& v) { std::vector x(v.size(), true); for (size_t i=0; i void cumsum(std::vector& v, bool narm) { if (narm) { for (size_t i=1; i::value; } else { v[i] += v[i-1]; } } } } template void cumprod(std::vector& v, bool narm) { if (narm) { for (size_t i=1; i::value; } else { v[i] *= v[i-1]; } } } } template void cummax(std::vector& v, bool narm) { if (narm) { for (size_t i=1; i::value; } else { v[i] = std::max(v[i], v[i-1]); } } } } template void cummin(std::vector& v, bool narm) { if (narm) { for (size_t i=1; i::value; } else { v[i] = std::min(v[i], v[i-1]); } } } } /* #include template std::vector order(const std::vector &v) { std::vector idx(v.size()); std::iota(idx.begin(), idx.end(), 0); stable_sort(idx.begin(), idx.end(), [&v](size_t i, size_t j) {return v[i] < v[j];}); return idx; } */ #endif terra/src/spatDataframe.h0000644000175000017500000000712014201035750015232 0ustar nileshnilesh// Copyright (c) 2018-2020 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include #include //#include "spatMessages.h" #include "spatBase.h" class SpatDataFrame { public: SpatDataFrame(); virtual ~SpatDataFrame(){} SpatDataFrame skeleton(); SpatMessages msg; void setError(std::string s) { msg.setError(s); } void addWarning(std::string s) { msg.addWarning(s); } bool hasError() { return msg.has_error; } bool hasWarning() { return msg.has_warning; } std::string getWarnings() { return msg.getWarnings(); } std::string getError() { return msg.getError(); } std::vector names; std::vector itype; //0 double, 1 long, 2 string std::vector iplace; std::vector< std::vector> dv; std::vector< std::vector> iv; std::vector< std::vector> sv; std::string NAS = "____NA_+"; unsigned nrow(); unsigned ncol(); SpatDataFrame subset_rows(std::vector range); SpatDataFrame subset_rows(std::vector range); SpatDataFrame subset_cols(std::vector range); SpatDataFrame subset_rows(unsigned i); SpatDataFrame subset_cols(unsigned i); std::vector getD(unsigned i); std::vector getI(unsigned i); std::vector getS(unsigned i); std::vector as_string(size_t v); std::vector as_long(size_t v); std::vector as_double(size_t v); double getDvalue(unsigned i, unsigned j); long getIvalue(unsigned i, unsigned j); std::string getSvalue(unsigned i, unsigned j); void add_row(); void add_rows(size_t n); //void set_values(std::vector x, std::string name); //void set_values(std::vector x, std::string name); //void set_values(std::vector x, std::string name); void add_column(unsigned dtype, std::string name); bool add_column(std::vector x, std::string name); bool add_column(std::vector x, std::string name); bool add_column(std::vector x, std::string name); bool add_column(std::vector x, std::string name); void insert_column(std::vector, size_t i); void insert_column(std::vector, size_t i); void insert_column(std::vector, size_t i); bool remove_column(std::string field); bool remove_column(int i); void resize_rows(unsigned n); void remove_rows(std::vector r); void resize_cols(unsigned n); void reserve(unsigned n); bool rbind(SpatDataFrame &x); bool cbind(SpatDataFrame &x); SpatDataFrame unique(int col); std::vector getIndex(int col, SpatDataFrame &x); std::vector get_names(); void set_names(std::vector nms); std::vector get_datatypes(); std::string get_datatype(std::string field); std::string get_datatype(int field); int get_fieldindex(std::string field); bool field_exists(std::string field); bool write_dbf(std::string filename, bool overwrite, SpatOptions &opt); }; terra/src/raster_stats.cpp0000644000175000017500000003632114202362664015544 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include "spatRaster.h" #include #include #include #include #include #include "vecmath.h" #include "math_utils.h" #include "string_utils.h" std::map table(std::vector &v) { std::map count; for_each( v.begin(), v.end(), [&count]( double val ){ if(!std::isnan(val)) count[val]++; } ); return count; } std::map ctable(std::map &x, std::map &y) { for(auto p : y) { x[p.first] += p.second; } return(x); } std::vector vtable(std::map &x) { std::vector> out(2); for( auto p : x ) { out[0].push_back(p.first); out[1].push_back(p.second); } out[0].insert(out[0].end(), out[1].begin(), out[1].end()); return out[0]; } std::vector> SpatRaster::freq(bool bylayer, bool round, int digits, SpatOptions &opt) { std::vector> out; if (!hasValues()) return out; BlockSize bs = getBlockSize(opt); unsigned nc = ncol(); unsigned nl = nlyr(); if (!readStart()) { return(out); } if (bylayer) { out.resize(nl); std::vector> tabs(nl); for (size_t i = 0; i < bs.n; i++) { unsigned nrc = bs.nrows[i] * nc; std::vector v; readValues(v, bs.row[i], bs.nrows[i], 0, nc); if (round) { for(double& d : v) d = roundn(d, digits); } for (size_t lyr=0; lyr vv(v.begin()+off, v.begin() + off + nrc); std::map tab = table(vv); tabs[lyr] = ctable(tabs[lyr], tab); } } for (size_t lyr=0; lyr tabs; for (size_t i = 0; i < bs.n; i++) { std::vector v; readValues(v, bs.row[i], bs.nrows[i], 0, nc); if (round) { for (double& d : v) d = roundn(d, digits); } std::map tab = table(v); tabs = ctable(tabs, tab); } out[0] = vtable(tabs); } readStop(); return(out); } std::vector SpatRaster::count(double value, bool bylayer, bool round, int digits, SpatOptions &opt) { std::vector out; if (!hasValues()) return out; BlockSize bs = getBlockSize(opt); unsigned nc = ncol(); unsigned nl = nlyr(); if (!readStart()) { return(out); } if (bylayer) { out.resize(nl); for (size_t i = 0; i < bs.n; i++) { unsigned nrc = bs.nrows[i] * nc; std::vector v; readValues(v, bs.row[i], bs.nrows[i], 0, nc); if (round) { for(double& d : v) d = roundn(d, digits); } if (std::isnan(value)) { for (size_t lyr=0; lyr v; readValues(v, bs.row[i], bs.nrows[i], 0, nc); if (round) { for (double& d : v) d = roundn(d, digits); } if (std::isnan(value)) { out[0] += count_if(v.begin(), v.end(), [](double d){return std::isnan(d);}); } else { out[0] += std::count(v.begin(), v.end(), value); } } } readStop(); return(out); } SpatRaster SpatRaster::quantile(std::vector probs, bool narm, SpatOptions &opt) { SpatRaster out = geometry(1); size_t n = probs.size(); if (n == 0) { out.setError("no probs"); return out; } else if (nlyr() < 2) { out.setError("more than one layer needed to compute quantiles"); return out; } double pmin = vmin(probs, false); double pmax = vmin(probs, false); if ((std::isnan(pmin)) | (std::isnan(pmax)) | (pmin < 0) | (pmax > 1)) { SpatRaster out = geometry(1); out.setError("intvalid probs"); return out; } out = geometry(probs.size()); out.source[0].names = double_to_string(probs, "q"); if (!hasValues()) { return out; } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } unsigned nl = nlyr(); std::vector v(nl); for (size_t i = 0; i < out.bs.n; i++) { std::vector a; readBlock(a, out.bs, i); unsigned nc = out.bs.nrows[i] * out.ncol(); std::vector b(nc * n); for (size_t j=0; j p = vquantile(v, probs, narm); for (size_t k=0; k &d) { d.erase(std::remove_if(d.begin(), d.end(), [](const double& value) { return std::isnan(value); }), d.end()); std::sort(d.begin(), d.end()); d.erase(std::unique(d.begin(), d.end()), d.end()); } void unique_values(std::vector &d) { d.erase(std::remove_if(d.begin(), d.end(), [](const double& value) { return std::isnan(value); }), d.end()); std::set u { d.begin(), d.end()}; std::copy(u.begin(), u.end(), d.begin()); d.erase(d.begin()+u.size(), d.end()); } std::vector> SpatRaster::unique(bool bylayer, SpatOptions &opt) { std::vector> out; if (!hasValues()) return out; constexpr double lowest_double = std::numeric_limits::lowest(); BlockSize bs = getBlockSize(opt); unsigned nc = ncol(); unsigned nl = nlyr(); if (!readStart()) { return(out); } out.resize(nl); if (nl == 1) bylayer = true; if (bylayer) { for (size_t i = 0; i < bs.n; i++) { unsigned n = bs.nrows[i] * nc; std::vector v; readValues(v, bs.row[i], bs.nrows[i], 0, nc); for (size_t lyr=0; lyr> temp; for (size_t i = 0; i < bs.n; i++) { unsigned n = bs.nrows[i] * nc; std::vector> m(n, std::vector(nl)); std::vector v; readValues(v, bs.row[i], bs.nrows[i], 0, nc); for (size_t j = 0; j < v.size(); j++) { if (std::isnan(v[j])) v[j] = lowest_double; } for (size_t lyr=0; lyr &u, const std::vector &v, const std::vector &z, std::string fun, bool narm, std::vector& out, std::vector &cnt) { if (fun=="sum") { if (narm) { for (size_t i=0; i f {"sum", "mean", "min", "max"}; if (std::find(f.begin(), f.end(), fun) == f.end()) { out.setError("not a valid function"); return(out); } if (!hasValues()) { out.setError("SpatRaster has no values"); return(out); } if (!z.hasValues()) { out.setError("zonal SpatRaster has no values"); return(out); } if (!compare_geom(z, false, true, opt.get_tolerance())) { out.setError("dimensions and/or extent do not match"); return(out); } if (z.nlyr() > 1) { SpatOptions xopt(opt); std::vector lyr = {0}; z = z.subset(lyr, xopt); out.addWarning("only the first zonal layer is used"); } size_t nl = nlyr(); std::vector> uq = z.unique(true, opt); std::vector u = uq[0]; double initv = 0; double posinf = std::numeric_limits::infinity(); double neginf = -posinf; if (fun == "max") initv = neginf; if (fun == "min") initv = posinf; std::vector> stats(nl, std::vector(u.size(), initv)); std::vector> cnt(nl, std::vector(u.size(), 0)); if (!readStart()) { out.setError(getError()); return(out); } if (!z.readStart()) { out.setError(z.getError()); return(out); } opt.ncopies = 6; BlockSize bs = getBlockSize(opt); for (size_t i=0; i v, zv; readValues(v, bs.row[i], bs.nrows[i], 0, ncol()); z.readValues(zv, bs.row[i], bs.nrows[i], 0, ncol()); std::vector zvr(zv.size()); for (size_t j=0; j 1) { for (size_t lyr=0; lyr vx( v.begin()+offset, v.begin()+offset+off); jointstats(u, vx, zvr, fun, narm, stats[lyr], cnt[lyr]); } } else { jointstats(u, v, zvr, fun, narm, stats[0], cnt[0]); } } readStop(); z.readStop(); if (fun=="mean") { for (size_t lyr=0; lyr 0) { stats[lyr][j] = stats[lyr][j] / cnt[lyr][j]; } else { stats[lyr][j] = NAN; } } } } else if (fun == "min") { for (size_t lyr=0; lyr nms = getNames(); for (size_t i=0; i f {"sum", "mean", "min", "max"}; if (std::find(f.begin(), f.end(), fun) == f.end()) { out.setError("not a valid function"); return(out); } if (!hasValues()) { out.setError("SpatRaster has no values"); return(out); } if (!z.hasValues()) { out.setError("zonal SpatRaster has no values"); return(out); } if (!compare_geom(z, false, true, opt.get_tolerance())) { out.setError("dimensions and/or extent do not match"); return(out); } if (z.nlyr() > 1) { SpatOptions xopt(opt); std::vector lyr = {0}; z = z.subset(lyr, xopt); out.addWarning("only the first zonal layer is used"); } size_t nl = nlyr(); std::vector> uq = z.unique(true, opt); std::vector u = uq[0]; double initv = 0; double posinf = std::numeric_limits::infinity(); double neginf = -posinf; if (fun == "max") initv = neginf; if (fun == "min") initv = posinf; std::vector> stats(nl, std::vector(u.size(), initv)); std::vector> cnt; if (fun == "mean") { cnt = std::vector>(nl, std::vector(u.size(), 0)); } if (!readStart()) { out.setError(getError()); return(out); } if (!z.readStart()) { out.setError(z.getError()); return(out); } opt.ncopies = 6; BlockSize bs = getBlockSize(opt); for (size_t i=0; i v, zv; readValues(v, bs.row[i], bs.nrows[i], 0, ncol()); z.readValues(zv, bs.row[i], bs.nrows[i], 0, ncol()); double zvold = zv[0]; if (!std::isnan(zv[0])) { auto it = find(u.begin(), u.end(), zv[0]); zv[0] = it - u.begin(); } for (size_t j=1; j 1) { for (size_t lyr=0; lyr vx( v.begin()+offset, v.begin()+offset+off); jointstats(u, vx, zv, fun, narm, stats[lyr], cnt[lyr]); } } else { jointstats(u, v, zv, fun, narm, stats[0], cnt[0]); } } readStop(); z.readStop(); if (fun=="mean") { for (size_t lyr=0; lyr 0) { stats[lyr][j] = stats[lyr][j] / cnt[lyr][j]; } else { stats[lyr][j] = NAN; } } } } else if (fun == "min") { for (size_t lyr=0; lyr nms = getNames(); for (size_t i=0; i #include "geos_spat.h" #include "distance.h" #include "recycle.h" #include "string_utils.h" SpatVector SpatVector::allerretour() { GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); SpatVector out = vect_from_geos(g, hGEOSCtxt, type()); geos_finish(hGEOSCtxt); return out; } SpatVectorCollection SpatVector::bienvenue() { GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); SpatVectorCollection out = coll_from_geos(g, hGEOSCtxt); geos_finish(hGEOSCtxt); return out; } std::vector SpatVector::wkt() { GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector out; out.reserve(g.size()); char * wkt; for (size_t i = 0; i < g.size(); i++) { wkt = GEOSGeomToWKT_r(hGEOSCtxt, g[i].get()); out.push_back(wkt); } geos_finish(hGEOSCtxt); return out; } std::vector SpatVector::wkb() { GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector out; out.reserve(g.size()); size_t len = 0; for (size_t i = 0; i < g.size(); i++) { unsigned char *wkb = GEOSGeomToWKB_buf_r(hGEOSCtxt, g[i].get(), &len); std::string s( reinterpret_cast(wkb), len) ; out.push_back(s); free(wkb); } geos_finish(hGEOSCtxt); return out; } std::vector SpatVector::hex() { GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector out; out.reserve(g.size()); size_t len = 0; for (size_t i = 0; i < g.size(); i++) { unsigned char *hex = GEOSGeomToHEX_buf_r(hGEOSCtxt, g[i].get(), &len); std::string s( reinterpret_cast(hex), len) ; out.push_back(s); free(hex); } geos_finish(hGEOSCtxt); return out; } SpatVector SpatVector::from_hex(std::vector x, std::string srs) { GEOSContextHandle_t hGEOSCtxt = geos_init(); size_t n = x.size(); std::vector p; p.resize(n); for (size_t i = 0; i < n; i++) { const char* cstr = x[i].c_str(); size_t len = strlen(cstr); const unsigned char *hex = (const unsigned char *) cstr; GEOSGeometry* r = GEOSGeomFromHEX_buf_r(hGEOSCtxt, hex, len); p[i] = geos_ptr(r, hGEOSCtxt); } SpatVectorCollection coll = coll_from_geos(p, hGEOSCtxt); geos_finish(hGEOSCtxt); SpatVector out = coll.get(0); out.setSRS(srs); return out; } std::vector SpatVector::geos_isvalid() { GEOSContextHandle_t hGEOSCtxt = geos_init2(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector out; out.reserve(g.size()); for (size_t i = 0; i < g.size(); i++) { char v = GEOSisValid_r(hGEOSCtxt, g[i].get()); out.push_back(v); } geos_finish(hGEOSCtxt); return {out}; } std::vector SpatVector::geos_isvalid_msg() { GEOSContextHandle_t hGEOSCtxt = geos_init2(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector out; out.reserve(2 * g.size()); for (size_t i = 0; i < g.size(); i++) { char v = GEOSisValid_r(hGEOSCtxt, g[i].get()); std::string valid = {v}; out.push_back(valid); if (!v) { char *r = GEOSisValidReason_r(hGEOSCtxt, g[i].get()); std::string reason = r; free(r); out.push_back(reason); } else { out.push_back(""); } } geos_finish(hGEOSCtxt); return {out}; } SpatVector SpatVector::make_valid2() { SpatVector out; #ifndef GEOS380 out.setError("make_valid is not available for GEOS < 3.8"); #else GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector x = geos_geoms(this, hGEOSCtxt); size_t n = size(); std::vector ids; ids.reserve(n); for (size_t i=0; i g = geos_geoms(this, hGEOSCtxt); std::vector p; p.reserve(g.size()); std::vector id; id.reserve(g.size()); for (size_t i = 0; i < g.size(); i++) { GEOSGeometry* r = GEOSClipByRect_r(hGEOSCtxt, g[i].get(), e.xmin, e.ymin, e.xmax, e.ymax); if (r == NULL) { out.setError("something bad happened"); geos_finish(hGEOSCtxt); return out; } if (!GEOSisEmpty_r(hGEOSCtxt, r)) { p.push_back(geos_ptr(r, hGEOSCtxt)); id.push_back(i); } else { GEOSGeom_destroy_r(hGEOSCtxt, r); } } if (p.size() > 0) { SpatVectorCollection coll = coll_from_geos(p, hGEOSCtxt, id); out = coll.get(0); out.df = df.subset_rows(out.df.iv[0]); out.srs = srs; } geos_finish(hGEOSCtxt); return out; #endif } SpatVector SpatVector::make_nodes() { SpatVector out; GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector p; p.reserve(g.size()); for (size_t i = 0; i < g.size(); i++) { GEOSGeometry* r = GEOSNode_r(hGEOSCtxt, g[i].get()); if (r == NULL) { out.setError("something bad happened"); geos_finish(hGEOSCtxt); return out; } if (!GEOSisEmpty_r(hGEOSCtxt, r)) { p.push_back(geos_ptr(r, hGEOSCtxt)); } else { GEOSGeom_destroy_r(hGEOSCtxt, r); } } if (p.size() > 0) { SpatVectorCollection coll = coll_from_geos(p, hGEOSCtxt); out = coll.get(0); out.df = df; } geos_finish(hGEOSCtxt); out.srs = srs; return out; } SpatVector SpatVector::boundary() { SpatVector out; GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector p; p.reserve(g.size()); for (size_t i = 0; i < g.size(); i++) { GEOSGeometry* r = GEOSBoundary_r(hGEOSCtxt, g[i].get()); if (r == NULL) { out.setError("something bad happened"); geos_finish(hGEOSCtxt); return out; } if (!GEOSisEmpty_r(hGEOSCtxt, r)) { p.push_back(geos_ptr(r, hGEOSCtxt)); } else { GEOSGeom_destroy_r(hGEOSCtxt, r); } } if (p.size() > 0) { SpatVectorCollection coll = coll_from_geos(p, hGEOSCtxt); out = coll.get(0); out.df = df; } geos_finish(hGEOSCtxt); out.srs = srs; return out; } SpatVector SpatVector::normalize() { SpatVector out; GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector p; p.reserve(g.size()); for (size_t i = 0; i < g.size(); i++) { GEOSGeometry* r = g[i].get(); if (GEOSNormalize_r(hGEOSCtxt, r)) { g[i] = geos_ptr(r, hGEOSCtxt); } else { GEOSGeom_destroy_r(hGEOSCtxt, r); } } out = vect_from_geos(g, hGEOSCtxt, type()); geos_finish(hGEOSCtxt); out.df = df; out.srs = srs; return out; } SpatVector SpatVector::line_merge() { SpatVector out; if (type() != "lines") { out.setError("input must be lines"); return out; } GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector p; p.reserve(g.size()); for (size_t i = 0; i < g.size(); i++) { GEOSGeometry* r = GEOSLineMerge_r(hGEOSCtxt, g[i].get()); if (r == NULL) { out.setError("something bad happened"); geos_finish(hGEOSCtxt); return out; } if (!GEOSisEmpty_r(hGEOSCtxt, r)) { p.push_back(geos_ptr(r, hGEOSCtxt)); } else { GEOSGeom_destroy_r(hGEOSCtxt, r); } } if (p.size() > 0) { SpatVectorCollection coll = coll_from_geos(p, hGEOSCtxt); out = coll.get(0); out.df = df; } geos_finish(hGEOSCtxt); out.srs = srs; return out; } SpatVector SpatVector::simplify(double tolerance, bool preserveTopology) { SpatVector out; GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector p; p.reserve(g.size()); for (size_t i = 0; i < g.size(); i++) { GEOSGeometry* r; if (preserveTopology) { r = GEOSTopologyPreserveSimplify_r(hGEOSCtxt, g[i].get(), tolerance); } else { r = GEOSSimplify_r(hGEOSCtxt, g[i].get(), tolerance); } if (r == NULL) { out.setError("something bad happened"); geos_finish(hGEOSCtxt); return out; } if (!GEOSisEmpty_r(hGEOSCtxt, r)) { p.push_back(geos_ptr(r, hGEOSCtxt)); } else { GEOSGeom_destroy_r(hGEOSCtxt, r); } } if (p.size() > 0) { SpatVectorCollection coll = coll_from_geos(p, hGEOSCtxt); out = coll.get(0); out.df = df; } geos_finish(hGEOSCtxt); out.srs = srs; return out; } SpatVector SpatVector::shared_paths() { if (type() == "polygons") { SpatVector x = as_lines(); return x.shared_paths(); } GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector x = geos_geoms(this, hGEOSCtxt); size_t s = size(); std::vector id1, id2; std::vector p; for (size_t i=0; i<(s-1); i++) { for (size_t j=(i+1); j 0) { SpatVectorCollection coll = coll_from_geos(p, hGEOSCtxt, std::vector(), false, false); out = coll.get(0); out = out.line_merge(); } geos_finish(hGEOSCtxt); out.srs = srs; out.df.add_column(id1, "id1"); out.df.add_column(id2, "id2"); return out; } /* SpatVector SpatVector::split_polygons(SpatVector lns) { SpatGeom glns; glns.gtype = lines; glns.setPart(SpatPart(x, y), 0); std::vector xln = {180, 180}; std::vector yln = {-91, 91}; glns.setPart(SpatPart(xln, yln), 1); SpatVector v; v.addGeom(glns); v = v.line_merge(); v = v.aggregate(false); v = v.polygonize(); g = v.geoms[0]; */ SpatVector SpatVector::polygonize() { SpatVector out; out.srs = srs; GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector p; p.reserve(g.size()); size_t ngeoms = 1; for (size_t i = 0; i < g.size(); i++) { const GEOSGeometry* gi = g[i].get(); GEOSGeometry* r = GEOSPolygonize_r(hGEOSCtxt, &gi, ngeoms); if (r == NULL) { out.setError("something bad happened"); geos_finish(hGEOSCtxt); return out; } if (!GEOSisEmpty_r(hGEOSCtxt, r)) { p.push_back(geos_ptr(r, hGEOSCtxt)); } else { GEOSGeom_destroy_r(hGEOSCtxt, r); } } if (p.size() > 0) { SpatVectorCollection coll = coll_from_geos(p, hGEOSCtxt); out = coll.get(0); out.srs = srs; out.df = df; } geos_finish(hGEOSCtxt); return out; } SpatVector SpatVector::snap(double tolerance) { size_t s = size(); SpatVector out; if (s == 0) { return out; } tolerance = std::max(0.0, tolerance); GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector x = geos_geoms(this, hGEOSCtxt); std::vector ids; ids.reserve(s); for (size_t i=0; i<(s-1); i++) { GEOSGeometry* r = x[i].get(); for (size_t j=(i+1); j x = geos_geoms(this, hGEOSCtxt); std::vector to = geos_geoms(&y, hGEOSCtxt); std::vector ids; ids.reserve(s); GEOSGeometry* gto = to[0].get(); for (size_t i=0; i x = geos_geoms(this, hGEOSCtxt); // if ((type() != "polygons") & (type() != "mutlipolygons")) { if ((type() != "polygons")) { v = v.hull("convex"); } else { v = v.aggregate(false); } std::vector y = geos_geoms(&v, hGEOSCtxt); std::vector result; std::vector ids; size_t nx = size(); ids.reserve(nx); for (size_t i = 0; i < nx; i++) { GEOSGeometry* geom = GEOSIntersection_r(hGEOSCtxt, x[i].get(), y[0].get()); if (geom == NULL) { out.setError("GEOS exception"); geos_finish(hGEOSCtxt); return(out); } if (!GEOSisEmpty_r(hGEOSCtxt, geom)) { result.push_back(geos_ptr(geom, hGEOSCtxt)); ids.push_back(i); } else { GEOSGeom_destroy_r(hGEOSCtxt, geom); } } // SpatVectorCollection coll = coll_from_geos(result, hGEOSCtxt); if (result.size() > 0) { // SpatVectorCollection coll = coll_from_geos(result, hGEOSCtxt); SpatVectorCollection coll = coll_from_geos(result, hGEOSCtxt, ids); out = coll.get(0); out.df = df.subset_rows(out.df.iv[0]); out.srs = srs; } geos_finish(hGEOSCtxt); return out; } SpatVector SpatVector::hull(std::string htype, std::string by) { SpatVector out; if (by != "") { SpatVector tmp = aggregate(by, false); if (tmp.hasError()) { return tmp; } for (size_t i=0; i 0) && (x.geoms[0].gtype == polygons)) { out.addGeom(x.geoms[0]); } else { SpatGeom g; g.gtype = polygons; out.addGeom(g); } } out.df = tmp.df; out.srs = out.srs; return out; } if (htype != "convex") { #ifndef GEOS361 out.setError("GEOS 3.6.1 required for rotated rectangle"); return out; #endif if (is_lonlat()) { if ((extent.ymin > -85) && (extent.ymax < 85)) { SpatVector tmp = project("+proj=merc"); tmp = tmp.hull(htype, ""); tmp = tmp.project(srs.wkt); return tmp; } } } GEOSContextHandle_t hGEOSCtxt = geos_init(); SpatVector a = aggregate(false); std::vector g = geos_geoms(&a, hGEOSCtxt); //std::string vt = type(); GEOSGeometry* h; if (htype == "convex") { h = GEOSConvexHull_r(hGEOSCtxt, g[0].get()); } else { #ifndef GEOS361 out.setError("GEOS 3.6.1 required for rotated rectangle"); return out; #else h = GEOSMinimumRotatedRectangle_r(hGEOSCtxt, g[0].get()); #endif } std::vector b(1); b[0] = geos_ptr(h, hGEOSCtxt); SpatVectorCollection coll = coll_from_geos(b, hGEOSCtxt); geos_finish(hGEOSCtxt); out = coll.get(0); out.srs = srs; return out; } SpatVector SpatVector::voronoi(SpatVector bnd, double tolerance, int onlyEdges) { SpatVector out; #ifndef GEOS350 out.setError("GEOS 3.5 required for voronoi"); return out; #else GEOSContextHandle_t hGEOSCtxt = geos_init(); SpatVector a = aggregate(false); std::vector g = geos_geoms(&a, hGEOSCtxt); GEOSGeometry* v; if (bnd.size() > 0) { if (bnd.type() != "polygons") { out.setError("boundary must be polygon"); geos_finish(hGEOSCtxt); return out; } std::vector ge = geos_geoms(&bnd, hGEOSCtxt); v = GEOSVoronoiDiagram_r(hGEOSCtxt, g[0].get(), ge[0].get(), tolerance, onlyEdges); } else { v = GEOSVoronoiDiagram_r(hGEOSCtxt, g[0].get(), NULL, tolerance, onlyEdges); } if (v == NULL) { out.setError("GEOS exception"); geos_finish(hGEOSCtxt); return(out); } std::vector b(1); b[0] = geos_ptr(v, hGEOSCtxt); SpatVectorCollection coll = coll_from_geos(b, hGEOSCtxt); geos_finish(hGEOSCtxt); out = coll.get(0); out.srs = srs; if (!out.hasError()) { out = out.disaggregate(); if (bnd.size() > 0) { SpatDataFrame empty; bnd.df = empty; out = out.intersect(bnd); } if ((type() == "points") && (!onlyEdges)) { std::vector atts = out.relateFirst(*this, "intersects"); std::vector a; a.reserve(atts.size()); for (size_t i=0; i=0) a.push_back(atts[i]); } if (a.size() == out.size()) { out.df = df.subset_rows(a); } } } return out; #endif } SpatVector SpatVector::delauny(double tolerance, int onlyEdges) { SpatVector out; #ifndef GEOS350 out.setError("GEOS 3.5 required for delauny"); return out; #else GEOSContextHandle_t hGEOSCtxt = geos_init(); SpatVector a = aggregate(false); std::vector g = geos_geoms(&a, hGEOSCtxt); GEOSGeometry* v = GEOSDelaunayTriangulation_r(hGEOSCtxt, g[0].get(), tolerance, onlyEdges); if (v == NULL) { out.setError("GEOS exception"); geos_finish(hGEOSCtxt); return(out); } std::vector b(1); b[0] = geos_ptr(v, hGEOSCtxt); SpatVectorCollection coll = coll_from_geos(b, hGEOSCtxt); geos_finish(hGEOSCtxt); out = coll.get(0); out.srs = srs; if (!out.hasError()) { out = out.disaggregate(); // associate with attributes } return out; #endif } SpatGeom hullify(SpatVector b, bool ispoly) { if (b.nrow() == 1) return b.geoms[0]; if (ispoly) b.addGeom(b.geoms[0]); SpatVector part; for (size_t j =0; j<(b.size()-1); j++) { std::vector range = {(unsigned)j, (unsigned)j+1}; SpatVector g = b.subset_rows(range); g = g.hull("convex"); part.addGeom(g.geoms[0]); } part = part.aggregate(true); return part.geoms[0]; } SpatVector lonlat_buf(SpatVector x, double dist, unsigned quadsegs, bool ispol, bool ishole) { if ((x.extent.ymin > -60) && (x.extent.ymax < 60) && ((x.extent.ymax - x.extent.ymin) < 1) && dist < 110000) { SpatSRS insrs = x.srs; x.setSRS("+proj=merc"); double f = 0.5 - (dist / 220000); double halfy = x.extent.ymin + f * (x.extent.ymax - x.extent.ymin); std::vector dd = destpoint_lonlat(0, halfy, 0, dist); dist = dd[1] - halfy; x = x.buffer({dist}, quadsegs); x.srs = insrs; return x; } SpatVector tmp; x = x.disaggregate(); for (size_t i =0; i d(p.size(), dist); SpatVector b = p.point_buffer(d, quadsegs, true); if (b.size() <= p.size()) { SpatGeom g = hullify(b, ispol); tmp.addGeom(g); } else { SpatVector west, east, eastwest; for (size_t j =0; j 179.99)) { tmp.addGeom(b.geoms[j]); } else if (b.geoms[j].extent.xmax < 0) { west.addGeom(b.geoms[j]); } else { east.addGeom(b.geoms[j]); } } if (east.nrow() > 0) { SpatGeom geast = hullify(east, ispol); tmp.addGeom(geast); } if (west.nrow() > 0) { SpatGeom gwest = hullify(west, ispol); tmp.addGeom(gwest); } } } tmp = tmp.aggregate(true); if (ispol) { tmp = ishole ? tmp.get_holes() : tmp.remove_holes(); } return tmp; } SpatVector SpatVector::buffer(std::vector dist, unsigned quadsegs) { quadsegs = std::min(quadsegs, (unsigned) 180); SpatVector out; out.srs = srs; if (srs.is_empty()) { out.setError("crs not defined"); return(out); } bool islonlat = is_lonlat(); if (dist.size() == 1 && dist[0] == 0) { islonlat = false; //faster } std::string vt = type(); if (vt == "points" || vt == "lines" || islonlat) { for (size_t i=0; i 0) { h = lonlat_buf(h, dist[i], quadsegs, true, true); if (h.size() > 0) { for (size_t j=0; j g = geos_geoms(this, hGEOSCtxt); std::vector b(size()); for (size_t i = 0; i < g.size(); i++) { GEOSGeometry* pt = GEOSBuffer_r(hGEOSCtxt, g[i].get(), dist[i], quadsegs); if (pt == NULL) { out.setError("GEOS exception"); geos_finish(hGEOSCtxt); return(out); } b[i] = geos_ptr(pt, hGEOSCtxt); } SpatVectorCollection coll = coll_from_geos(b, hGEOSCtxt); // out = spat_from_geom(hGEOSCtxt, g, "points"); geos_finish(hGEOSCtxt); out = coll.get(0); out.srs = srs; out.df = df; return out; } SpatVector SpatVector::intersect(SpatVector v) { SpatVector out; out.srs = srs; GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector x = geos_geoms(this, hGEOSCtxt); //v = v.aggregate(false); std::vector y = geos_geoms(&v, hGEOSCtxt); std::vector result; size_t nx = size(); size_t ny = v.size(); std::vector idx, idy; std::vector ids; idx.reserve(nx); idy.reserve(ny); if (type() == "points") { //std::vector ixj(nx, false); //size_t count = 0; for (size_t j = 0; j < ny; j++) { PrepGeomPtr pr = geos_ptr(GEOSPrepare_r(hGEOSCtxt, y[j].get()), hGEOSCtxt); for (size_t i = 0; i < nx; i++) { if (GEOSPreparedIntersects_r(hGEOSCtxt, pr.get(), x[i].get())) { //if (!ixj[i] //ixj[i] = true; idx.push_back(i); idy.push_back(j); //count++; } } } //std::vector sx; //sx.reserve(count); //for (size_t i=0; i 0) { SpatVectorCollection coll = coll_from_geos(result, hGEOSCtxt, ids); out = coll.get(0); out.srs = srs; } } geos_finish(hGEOSCtxt); if (!srs.is_same(v.srs, true)) { out.addWarning("different crs"); } if ((type() == "polygons") && (v.type() == "polygons") && (out.type() != "polygons")) { // intersection is point or line, return empty out = SpatVector(); out.addWarning("no intersection"); out.srs = srs; } SpatDataFrame df1, df2; size_t n = out.nrow(); if (n < idx.size()) { std::vector idx2, idy2; idx2.reserve(n); idy2.reserve(n); for (size_t i=0; i getRelateFun(const std::string rel) { std::function rfun; if (rel == "intersects") { rfun = GEOSIntersects_r; } else if (rel == "disjoint") { rfun = GEOSDisjoint_r; } else if (rel == "touches") { rfun = GEOSTouches_r; } else if (rel == "crosses") { rfun = GEOSCrosses_r; } else if (rel == "within") { rfun = GEOSWithin_r; } else if (rel == "contains") { rfun = GEOSContains_r; } else if (rel == "containsproperly") { rfun = GEOSContainsProperly_r; } else if (rel == "overlaps") { rfun = GEOSOverlaps_r; } else if (rel == "covers") { rfun = GEOSCovers_r; } else if (rel == "coveredby") { rfun = GEOSCoveredBy_r; } return rfun; } */ std::function getPrepRelateFun(const std::string rel) { std::function rfun; if (rel == "intersects") { rfun = GEOSPreparedIntersects_r; } else if (rel == "disjoint") { rfun = GEOSPreparedDisjoint_r; } else if (rel == "touches") { rfun = GEOSPreparedTouches_r; } else if (rel == "crosses") { rfun = GEOSPreparedCrosses_r; } else if (rel == "within") { rfun = GEOSPreparedWithin_r; } else if (rel == "contains") { rfun = GEOSPreparedContains_r; } else if (rel == "containsproperly") { rfun = GEOSPreparedContainsProperly_r; } else if (rel == "overlaps") { rfun = GEOSPreparedOverlaps_r; } else if (rel == "covers") { rfun = GEOSPreparedCovers_r; } else if (rel == "coveredby") { rfun = GEOSPreparedCoveredBy_r; } return rfun; } int getRel(std::string &relation) { int pattern = 1; std::string rel = relation; std::transform(rel.begin(), rel.end(), rel.begin(), ::tolower); std::vector f {"rook", "queen", "intersects", "touches", "crosses", "overlaps", "within", "contains", "covers", "coveredby", "disjoint"}; if (std::find(f.begin(), f.end(), rel) == f.end()) { if (relation.size() != 9) { pattern = 2; } else { std::string r = relation; for (size_t i=0; i<9; i++) { if (!(r.at(i) == 'T' || r.at(i) == 'F' || r.at(i) == '0' || r.at(i) == '1' || r.at(i) == '2' || r.at(i) == '*')) { pattern = 2; break; } } } } else if (rel == "rook") { relation = "F***1****"; } else if (rel == "queen") { relation = "F***T****"; } else { pattern = 0; relation = rel; } return pattern; } std::vector SpatVector::relate(SpatVector v, std::string relation) { std::vector out; int pattern = getRel(relation); if (pattern == 2) { setError("'" + relation + "'" + " is not a valid relate name or pattern"); return out; } GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector x = geos_geoms(this, hGEOSCtxt); std::vector y = geos_geoms(&v, hGEOSCtxt); size_t nx = size(); size_t ny = v.size(); out.reserve(nx*ny); if (pattern == 1) { for (size_t i = 0; i < nx; i++) { for (size_t j = 0; j < ny; j++) { out.push_back( GEOSRelatePattern_r(hGEOSCtxt, x[i].get(), y[j].get(), relation.c_str())); } } } else { std::function relFun = getPrepRelateFun(relation); for (size_t i = 0; i < nx; i++) { PrepGeomPtr pr = geos_ptr(GEOSPrepare_r(hGEOSCtxt, x[i].get()), hGEOSCtxt); for (size_t j = 0; j < ny; j++) { out.push_back( relFun(hGEOSCtxt, pr.get(), y[j].get())); } } } geos_finish(hGEOSCtxt); return out; } std::vector SpatVector::relateFirst(SpatVector v, std::string relation) { int pattern = getRel(relation); if (pattern == 2) { setError("'" + relation + "'" + " is not a valid relate name or pattern"); std::vector out; return out; } GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector x = geos_geoms(this, hGEOSCtxt); std::vector y = geos_geoms(&v, hGEOSCtxt); size_t nx = size(); size_t ny = v.size(); std::vector out(nx, -1); if (pattern == 1) { for (size_t i = 0; i < nx; i++) { for (size_t j = 0; j < ny; j++) { if (GEOSRelatePattern_r(hGEOSCtxt, x[i].get(), y[j].get(), relation.c_str())) { out[i] = j; continue; } } } } else { //std::function relFun = getRelateFun(relation); std::function relFun = getPrepRelateFun(relation); for (size_t i = 0; i < nx; i++) { PrepGeomPtr pr = geos_ptr(GEOSPrepare_r(hGEOSCtxt, x[i].get()), hGEOSCtxt); for (size_t j = 0; j < ny; j++) { if (relFun(hGEOSCtxt, pr.get(), y[j].get())) { out[i] = j; continue; } } } } geos_finish(hGEOSCtxt); return out; } std::vector SpatVector::relate(std::string relation, bool symmetrical) { std::vector out; int pattern = getRel(relation); if (pattern == 2) { setError("'" + relation + "'" + " is not a valid relate name or pattern"); return out; } GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector x = geos_geoms(this, hGEOSCtxt); if (symmetrical) { size_t s = size(); size_t n = ((s-1) * s)/2; out.reserve(n); if (pattern == 1) { for (size_t i=0; i<(s-1); i++) { for (size_t j=(i+1); j relFun = getPrepRelateFun(relation); for (size_t i=0; i<(s-1); i++) { PrepGeomPtr pr = geos_ptr(GEOSPrepare_r(hGEOSCtxt, x[i].get()), hGEOSCtxt); for (size_t j=(i+1); j relFun = getPrepRelateFun(relation); for (size_t i = 0; i < nx; i++) { PrepGeomPtr pr = geos_ptr(GEOSPrepare_r(hGEOSCtxt, x[i].get()), hGEOSCtxt); for (size_t j = 0; j < nx; j++) { out.push_back( relFun(hGEOSCtxt, pr.get(), x[j].get())); } } } } geos_finish(hGEOSCtxt); return out; } std::vector SpatVector::is_related(SpatVector v, std::string relation) { std::vector out; int pattern = getRel(relation); if (pattern == 2) { setError("'" + relation + "'" + " is not a valid relate name or pattern"); return out; } GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector x = geos_geoms(this, hGEOSCtxt); std::vector y = geos_geoms(&v, hGEOSCtxt); size_t nx = size(); size_t ny = v.size(); out.resize(nx, false); if (pattern == 1) { for (size_t i = 0; i < nx; i++) { for (size_t j = 0; j < ny; j++) { bool isrel = GEOSRelatePattern_r(hGEOSCtxt, x[i].get(), y[j].get(), relation.c_str()); if (isrel) { out[i] = true; continue; } } } } else { std::function relFun = getPrepRelateFun(relation); for (size_t i = 0; i < nx; i++) { PrepGeomPtr pr = geos_ptr(GEOSPrepare_r(hGEOSCtxt, x[i].get()), hGEOSCtxt); for (size_t j = 0; j < ny; j++) { bool isrel = relFun(hGEOSCtxt, pr.get(), y[j].get()); if (isrel) { out[i] = true; continue; } } } } geos_finish(hGEOSCtxt); return out; } SpatVector SpatVector::mask(SpatVector x, bool inverse) { std::vector b = is_related(x, "intersects"); if (inverse) { for (size_t i=0; i r; r.reserve(b.size()); for (size_t i=0; i SpatVector::geos_distance(SpatVector v, bool parallel) { std::vector out; size_t nx = size(); size_t ny = v.size(); GEOSContextHandle_t hGEOSCtxt = geos_init(); /* recycling, not a good idea here std::vector x; std::vector y; if ((parallel) && (nx != ny) && (nx > 1) && (ny > 1)) { SpatVector rr; if (ny < nx) { rr = v; ny = nx; recycle(rr.geoms, nx); x = geos_geoms(this, hGEOSCtxt); y = geos_geoms(&rr, hGEOSCtxt); } else { rr = *this; recycle(rr.geoms, ny); nx = ny; x = geos_geoms(&rr, hGEOSCtxt); y = geos_geoms(&v, hGEOSCtxt); } } else { x = geos_geoms(this, hGEOSCtxt); y = geos_geoms(&v, hGEOSCtxt); } */ std::vector x = geos_geoms(this, hGEOSCtxt); std::vector y = geos_geoms(&v, hGEOSCtxt); double d; if (parallel) { bool nyone = false; if (nx != ny) { if (ny == 1) { nyone = true; } else if ((nx == 1) && (ny > 1)) { std::swap(x, y); std::swap(nx, ny); nyone = true; } else { setError("vectors have different lengths"); return out; } } if (nyone) { out.reserve(nx); for (size_t i = 0; i < nx; i++) { if ( GEOSDistance_r(hGEOSCtxt, x[i].get(), y[0].get(), &d)) { out.push_back(d); } else { out.push_back(NAN); } } } else { out.reserve(nx); for (size_t i = 0; i < nx; i++) { if ( GEOSDistance_r(hGEOSCtxt, x[i].get(), y[i].get(), &d)) { out.push_back(d); } else { out.push_back(NAN); } } } } else { out.reserve(nx*ny); for (size_t i = 0; i < nx; i++) { for (size_t j = 0; j < ny; j++) { if ( GEOSDistance_r(hGEOSCtxt, x[i].get(), y[j].get(), &d)) { out.push_back(d); } else { out.push_back(NAN); } } } } geos_finish(hGEOSCtxt); return out; } std::vector SpatVector::geos_distance(bool sequential) { std::vector out; GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector x = geos_geoms(this, hGEOSCtxt); size_t s = size(); double d; if (sequential) { out.reserve(s); out.push_back(0); for (size_t i=0; i<(s-1); i++) { if ( GEOSDistance_r(hGEOSCtxt, x[i].get(), x[i+1].get(), &d)) { out.push_back(d); } else { out.push_back(NAN); } } } else { out.reserve((s-1) * s / 2); for (size_t i=0; i<(s-1); i++) { for (size_t j=(i+1); j x(1, 1); SpatDataFrame d; d.add_column(x, "id_1"); SpatVector out = subset_rows(0); out.df = d; for (int i=1; i x = geos_geoms(this, hGEOSCtxt); std::vector y = geos_geoms(&v, hGEOSCtxt); std::vector result; std::vector ids; ids.reserve(size()); size_t nx = size(); size_t ny = v.size(); for (size_t i = 0; i < nx; i++) { GEOSGeometry* geom = x[i].get(); for (size_t j = 0; j < ny; j++) { geom = GEOSDifference_r(hGEOSCtxt, geom, y[j].get()); if (geom == NULL) { out.setError("GEOS exception"); geos_finish(hGEOSCtxt); return(out); } if (GEOSisEmpty_r(hGEOSCtxt, geom)) { break; } } if (!GEOSisEmpty_r(hGEOSCtxt, geom)) { result.push_back(geos_ptr(geom, hGEOSCtxt)); ids.push_back(i); } else { GEOSGeom_destroy_r(hGEOSCtxt, geom); } } if (result.size() > 0) { SpatVectorCollection coll = coll_from_geos(result, hGEOSCtxt); out = coll.get(0); out.srs = srs; out.df = df.subset_rows(ids); } geos_finish(hGEOSCtxt); if (!srs.is_same(v.srs, true)) { out.addWarning("different crs"); } return out.append(v, true); */ } SpatVector SpatVector::cover(SpatVector v, bool identity) { if (v.srs.is_empty()) { v.srs = srs; } SpatVector out = erase(v); if (identity) { SpatVector insect = intersect(v); v = v.erase(insect); out = out.append(insect, true); out = out.append(v, true); } else { out = out.append(v, true); } return out; } SpatVector SpatVector::erase_agg(SpatVector v) { if ((type() == "points") || (v.type() == "points")) { std::vector b = relateFirst(v, "intersects"); std::vector r; r.reserve(b.size()); for (size_t i=0; i < b.size(); i++) { if (b[i] == -1) r.push_back(i); } return subset_rows(r); } SpatVector out; GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector x = geos_geoms(this, hGEOSCtxt); // this approach is nicer than the below in ::erase // but it fails if polys overlap v = v.aggregate(false); std::vector y = geos_geoms(&v, hGEOSCtxt); std::vector rids; size_t nx = size(); std::vector result; for (size_t i = 0; i < nx; i++) { GEOSGeometry* geom = GEOSDifference_r(hGEOSCtxt, x[i].get(), y[0].get()); if (geom == NULL) { out.setError("GEOS exception"); geos_finish(hGEOSCtxt); return(out); } if (GEOSisEmpty_r(hGEOSCtxt, geom)) { GEOSGeom_destroy_r(hGEOSCtxt, geom); } else { result.push_back(geos_ptr(geom, hGEOSCtxt)); rids.push_back(i); } } if (result.size() > 0) { SpatVectorCollection coll = coll_from_geos(result, hGEOSCtxt); out = coll.get(0); out.srs = srs; out.df = df.subset_rows(rids); } else { std::vector none(1, -1); out = subset_rows(none); } geos_finish(hGEOSCtxt); if (!srs.is_same(v.srs, true)) { out.addWarning("different crs"); } return out; } SpatVector SpatVector::erase(SpatVector v) { if ((type() == "points") || (v.type() == "points")) { std::vector b = relateFirst(v, "intersects"); std::vector r; r.reserve(b.size()); for (size_t i=0; i x = geos_geoms(this, hGEOSCtxt); std::vector y = geos_geoms(&v, hGEOSCtxt); size_t nx = size(); size_t ny = v.size(); std::vector rids; rids.reserve(nx); for (size_t i = 0; i < nx; i++) { bool good=true; for (size_t j = 0; j < ny; j++) { GEOSGeometry* geom = GEOSDifference_r(hGEOSCtxt, x[i].get(), y[j].get()); if (geom == NULL) { out.setError("GEOS exception"); geos_finish(hGEOSCtxt); return(out); } if (GEOSisEmpty_r(hGEOSCtxt, geom)) { GEOSGeom_destroy_r(hGEOSCtxt, geom); good = false; break; } x[i] = geos_ptr(geom, hGEOSCtxt); } if (good) rids.push_back(i); } if (rids.size() > 0) { SpatVectorCollection coll = coll_from_geos(x, hGEOSCtxt); out = coll.get(0); out.srs = srs; out.df = df; if (rids.size() != out.nrow()) { out = out.subset_rows(rids); } } else { std::vector none(1, -1); out = subset_rows(none); } geos_finish(hGEOSCtxt); if (!srs.is_same(v.srs, true)) { out.addWarning("different crs"); } return out; } /* SpatVector SpatVector::erase(SpatVector v) { if ((type() == "points") || (v.type() == "points")) { std::vector b = relateFirst(v, "intersects"); std::vector r; r.reserve(b.size()); for (size_t i=0; i x = geos_geoms(this, hGEOSCtxt); std::vector y = geos_geoms(&v, hGEOSCtxt); std::vector rids; size_t nx = size(); size_t ny = v.size(); for (size_t i = 0; i < nx; i++) { //GEOSGeometry* geom = x[i].get(); for (size_t j = 0; j < ny; j++) { GEOSGeometry* geom = GEOSDifference_r(hGEOSCtxt, x[i].get(), y[j].get()); if (geom == NULL) { out.setError("GEOS exception"); geos_finish(hGEOSCtxt); return(out); } if (GEOSisEmpty_r(hGEOSCtxt, geom)) { GEOSGeom_destroy_r(hGEOSCtxt, geom); rids.push_back(i); break; } x[i] = geos_ptr(geom, hGEOSCtxt); } } if (rids.size() < nx) { SpatVectorCollection coll = coll_from_geos(x, hGEOSCtxt); out = coll.get(0); out.df = df; out.df.remove_rows(rids); } geos_finish(hGEOSCtxt); if (!srs.is_same(v.srs, true)) { out.addWarning("different crs"); } out.srs = srs; return out; } */ SpatVector SpatVector::erase() { SpatVector out; if (type() != "polygons") { out.setError("not polygons"); return out; } size_t n = size(); if (n < 2) { return *this; } GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector x = geos_geoms(this, hGEOSCtxt); std::vector rids; for (size_t i = 0; i < (n-1); i++) { for (size_t j = (i+1); j < n; j++) { GEOSGeometry* geom = GEOSDifference_r(hGEOSCtxt, x[i].get(), x[j].get()); if (geom == NULL) { out.setError("GEOS exception"); geos_finish(hGEOSCtxt); return(out); } else if (GEOSisEmpty_r(hGEOSCtxt, geom)) { GEOSGeom_destroy_r(hGEOSCtxt, geom); rids.push_back(i); break; } else { x[i] = geos_ptr(geom, hGEOSCtxt); } } } SpatVectorCollection coll = coll_from_geos(x, hGEOSCtxt); out = coll.get(0); out.srs = srs; out.df = df; out.df.remove_rows(rids); //SpatVector last = subset_rows(n-1); //out = out.append(last, true); geos_finish(hGEOSCtxt); return out; } SpatVector SpatVector::gaps() { SpatVector out; if (type() != "polygons") { out.setError("not polygons"); return out; } size_t n = size(); if (n < 2) { out.srs = srs; return out; } out = aggregate(true); return out.get_holes(); /* SpatExtent e = extent; e.xmin -= 11; e.xmax += 10; e.ymin -= 10; e.ymax += 10; SpatVector p(e, ""); p = p.erase(*this); p = p.disaggregate(); double exmin = e.xmin + 1; unsigned j; for (size_t i=0; i r(1, j); p.srs = srs; return p.remove_rows(r); */ } SpatVector SpatVector::nearest_point(SpatVector v, bool parallel) { SpatVector out; if ((size() == 0) || (v.size()==0)) { out.setError("empty SpatVecor(s)"); return out; } if (!srs.is_equal(v.srs)) { out.setError("CRSs do not match"); return out; } out.srs = srs; if (is_lonlat()) { if (type() == "points") { std::vector nlon, nlat, dist; std::vector id; std::vector> p = coordinates(); std::vector> pv = v.coordinates(); nearest_lonlat(id, dist, nlon, nlat, p[0], p[1], pv[0], pv[1]); out.setPointsGeometry(nlon, nlat); std::vector fromid(id.size()); std::iota(fromid.begin(), fromid.end(), 0); out.df.add_column(fromid, "from_id"); out.df.add_column(p[0], "from_x"); out.df.add_column(p[1], "from_y"); out.df.add_column(id, "to_id"); out.df.add_column(nlon, "to_x"); out.df.add_column(nlat, "to_y"); out.df.add_column(dist, "distance"); return out; } else { out.setError("not yet implement for non-point lonlat vector data"); return out; } } GEOSContextHandle_t hGEOSCtxt = geos_init(); if (parallel) { if ((size() != v.size())) { out.setError("SpatVecors do not have the same size"); return out; } std::vector x = geos_geoms(this, hGEOSCtxt); std::vector y = geos_geoms(&v, hGEOSCtxt); std::vector b(size()); for (size_t i=0; i < x.size(); i++) { GEOSCoordSequence* csq = GEOSNearestPoints_r(hGEOSCtxt, x[i].get(), y[i].get()); GEOSGeometry* geom = GEOSGeom_createLineString_r(hGEOSCtxt, csq); b[i] = geos_ptr(geom, hGEOSCtxt); } out = vect_from_geos(b, hGEOSCtxt, "lines"); } else { SpatVector mp = v.aggregate(false); std::vector x = geos_geoms(this, hGEOSCtxt); std::vector y = geos_geoms(&mp, hGEOSCtxt); std::vector b(size()); for (size_t i = 0; i < x.size(); i++) { GEOSCoordSequence* csq = GEOSNearestPoints_r(hGEOSCtxt, x[i].get(), y[0].get()); GEOSGeometry* geom = GEOSGeom_createLineString_r(hGEOSCtxt, csq); b[i] = geos_ptr(geom, hGEOSCtxt); } out = vect_from_geos(b, hGEOSCtxt, "lines"); } geos_finish(hGEOSCtxt); out.srs = srs; return out; } SpatVector SpatVector::nearest_point() { SpatVector out; if ((size() == 0)) { out.addWarning("empty SpatVecor"); return out; } if ((size() == 1)) { out.addWarning("single geometry"); //return *this; } size_t n = size(); out.srs = srs; if (is_lonlat()) { if (type() == "points") { std::vector nlon, nlat, dist; std::vector id; std::vector> p = coordinates(); nearest_lonlat_self(id, dist, nlon, nlat, p[0], p[1]); out.setPointsGeometry(nlon, nlat); out.df.add_column(id, "id"); out.df.add_column(dist, "distance"); return out; } else { out.setError("not yet implement for non-point lonlat vector data"); return out; } } GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector x = geos_geoms(this, hGEOSCtxt); std::vector b(n); for (unsigned i = 0; i < n; i++) { SpatVector xa = remove_rows({i}); xa = xa.aggregate(false); std::vector y = geos_geoms(&xa, hGEOSCtxt); GEOSCoordSequence* csq = GEOSNearestPoints_r(hGEOSCtxt, x[i].get(), y[0].get()); GEOSGeometry* geom = GEOSGeom_createLineString_r(hGEOSCtxt, csq); b[i] = geos_ptr(geom, hGEOSCtxt); } out = vect_from_geos(b, hGEOSCtxt, "lines"); geos_finish(hGEOSCtxt); out.srs = srs; return out; } SpatVector SpatVector::cross_dateline(bool &fixed) { SpatVector out; fixed = false; if (type() == "points") { return out; } for (size_t i=0; i 1) && ((geoms[i].extent.xmax - geoms[i].extent.xmin) > 180)) { SpatGeom g = geoms[i]; for (size_t j=0; j g = geos_geoms(this, hGEOSCtxt); std::vector b(size()); for (size_t i = 0; i < g.size(); i++) { GEOSGeometry* pt = GEOSGetCentroid_r(hGEOSCtxt, g[i].get()); if (pt == NULL) { out.setError("NULL geom"); geos_finish(hGEOSCtxt); return out; } b[i] = geos_ptr(pt, hGEOSCtxt); } out = vect_from_geos(b, hGEOSCtxt, "points"); geos_finish(hGEOSCtxt); out.srs = srs; out.df = df; return out; } SpatVector SpatVector::unaryunion() { SpatVector out; GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector gout(g.size()); for (size_t i = 0; i < g.size(); i++) { GEOSGeometry* u = GEOSUnaryUnion_r(hGEOSCtxt, g[i].get()); if (u == NULL) { out.setError("NULL geom"); geos_finish(hGEOSCtxt); return out; } gout[i] = geos_ptr(u, hGEOSCtxt); } SpatVectorCollection coll = coll_from_geos(gout, hGEOSCtxt); geos_finish(hGEOSCtxt); out = coll.get(0); out.srs = srs; return out; } /* bool geos_buffer(GEOSContextHandle_t hGEOSCtxt, std::vector &g, double dist, unsigned nQuadSegs) { std::vector g(size()); for (size_t i = 0; i < g.size(); i++) { GEOSGeometry* pt = GEOSBuffer_r(hGEOSCtxt, g[i].get(), dist, nQuadSegs); if (pt == NULL) { return false; } g[i] = geos_ptr(pt, hGEOSCtxt); } return true; } */ SpatVector SpatVector::width() { SpatVector tmp; #ifndef GEOS361 tmp.setError("GEOS 3.6.1 required for width"); return tmp; #else GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector gout(g.size()); for (size_t i = 0; i < g.size(); i++) { GEOSGeometry* w = GEOSMinimumWidth_r(hGEOSCtxt, g[i].get()); if (w == NULL) { tmp.setError("found NULL geom"); geos_finish(hGEOSCtxt); return tmp; } gout[i] = geos_ptr(w, hGEOSCtxt); } SpatVectorCollection coll = coll_from_geos(gout, hGEOSCtxt); geos_finish(hGEOSCtxt); tmp = coll.get(0); tmp.srs = srs; return tmp; #endif } SpatVector SpatVector::clearance() { SpatVector tmp; #ifndef GEOS361 tmp.setError("GEOS 3.6 required for clearance"); return tmp; #else GEOSContextHandle_t hGEOSCtxt = geos_init(); std::vector g = geos_geoms(this, hGEOSCtxt); std::vector gout(g.size()); for (size_t i = 0; i < g.size(); i++) { GEOSGeometry* w = GEOSMinimumClearanceLine_r(hGEOSCtxt, g[i].get()); if (w == NULL) { tmp.setError("NULL geom"); geos_finish(hGEOSCtxt); return tmp; } gout[i] = geos_ptr(w, hGEOSCtxt); } SpatVectorCollection coll = coll_from_geos(gout, hGEOSCtxt); geos_finish(hGEOSCtxt); tmp = coll.get(0); tmp.srs = srs; return tmp; #endif } terra/src/spatBase.cpp0000644000175000017500000002702414201035750014560 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include "spatRaster.h" #include "string_utils.h" #include "math_utils.h" SpatOptions::SpatOptions() {} SpatOptions::SpatOptions(const SpatOptions &opt) { tempdir = opt.tempdir; memfrac = opt.memfrac; memmax = opt.memmax; todisk = opt.todisk; tolerance = opt.tolerance; def_datatype = opt.def_datatype; def_filetype = opt.def_filetype; filenames = {""}; overwrite = false; progress = opt.progress; ncopies = opt.ncopies; verbose = opt.verbose; def_verbose = opt.def_verbose; statistics = opt.statistics; steps = opt.steps; minrows = opt.minrows; names = opt.names; //ncdfcopy = opt.ncdfcopy; gdal_options = opt.gdal_options; overwrite = opt.overwrite; hasNAflag = false; NAflag = NAN; datatype_set = opt.datatype_set; datatype = opt.datatype; filetype = opt.filetype; pid = opt.pid + 1000; } SpatOptions SpatOptions::deepCopy() { return *this; } //SpatOptions SpatOptions::deepCopy(const SpatOptions &opt) { // return SpatOptions(opt); //} //void SpatOptions::set_def_bandorder(std::string d) { def_bandorder = d; } //std::string SpatOptions::get_def_bandorder() { return def_bandorder; } //void SpatOptions::set_bandorder(std::string d) { bandorder = d; } //std::string SpatOptions::get_bandorder() {if (bandorder != "") {return bandorder;} else {return def_datatype;}} void SpatOptions::set_def_datatype(std::string d) { std::vector ss = {"INT1U", "INT2U", "INT4U", "INT2S", "INT4S", "FLT4S", "FLT8S" } ; if (is_in_vector(d, ss)) def_datatype = d; } std::string SpatOptions::get_def_datatype() { return def_datatype; } void SpatOptions::set_datatype(std::string d) { std::vector ss = {"INT1U", "INT2U", "INT4U", "INT2S", "INT4S", "FLT4S", "FLT8S" }; if (is_in_vector(d, ss)) datatype = d; } std::string SpatOptions::get_datatype() {if (datatype != "") {return datatype;} else {return def_datatype;}} void SpatOptions::set_def_filetype(std::string d) { def_filetype = d; } std::string SpatOptions::get_def_filetype() { return def_filetype;} void SpatOptions::set_filetype(std::string d) { filetype = d; } std::string SpatOptions::get_filetype() { return filetype;} bool SpatOptions::get_overwrite() { return overwrite; } void SpatOptions::set_overwrite(bool b) { overwrite = b; } //bool SpatOptions::get_append() { return append; } //void SpatOptions::set_append(bool b) { append = b; } int SpatOptions::get_statistics() { return statistics; } void SpatOptions::set_statistics(int s) { if ((s> 0) && (s<7)) statistics = s; } //bool SpatOptions::get_ncdfcopy() { return ncdfcopy;} //void SpatOptions::set_ncdfcopy(bool x) { ncdfcopy = x; } void SpatOptions::set_def_verbose(bool v) { def_verbose = v; } bool SpatOptions::get_def_verbose() { return def_verbose; } bool SpatOptions::get_verbose() { return verbose; } void SpatOptions::set_verbose(bool v) { verbose = v; } bool SpatOptions::has_NAflag(double &flag) { flag = NAflag; return hasNAflag; } double SpatOptions::get_NAflag() { return NAflag; } void SpatOptions::set_NAflag(double flag) { NAflag = flag; hasNAflag = true; } unsigned SpatOptions::get_progress() { return progress; } void SpatOptions::set_progress(unsigned p) { progress = p; } bool SpatOptions::show_progress(unsigned n) { return ((progress > 0) & (progress <= n)); } //void SpatOptions::set_filename(std::string f) { // f = lrtrim_copy(f); // filenames = {f}; //} void SpatOptions::set_filenames(std::vector f) { for (size_t i=0; i SpatOptions::get_filenames() { if (!filenames.empty() ) { return filenames; } else { return {""}; } } std::string SpatOptions::get_tempdir() { return tempdir; } void SpatOptions::set_tempdir(std::string d) { // check if exists? tempdir = d; } double SpatOptions::get_memfrac() { return memfrac; } void SpatOptions::set_memfrac(double d) { // allowing very high values for testing purposes if ((d >= 0) && (d <= 100)) { memfrac = d; } } double SpatOptions::get_memmax() { return memmax; } void SpatOptions::set_memmax(double d) { if (std::isnan(d) || (d <= 0)) { memmax = -1; } else { memmax = d * 1024 * 1024 * 1024 / 8; } } double SpatOptions::get_tolerance() { return tolerance; } void SpatOptions::set_tolerance(double d) { if (d > 0) { tolerance = d; } } bool SpatOptions::get_todisk() { return todisk; } void SpatOptions::set_todisk(bool b) { todisk = b; } void SpatOptions::set_steps(size_t n) { steps = std::max((size_t)1, n); } size_t SpatOptions::get_steps(){ return steps; } void SpatOptions::set_ncopies(size_t n) { ncopies = std::max((size_t)1, n); } size_t SpatOptions::get_ncopies(){ return ncopies; } bool extent_operator(std::string oper) { std::vector f {"==", "!=", ">", "<", ">=", "<="}; return (std::find(f.begin(), f.end(), oper) != f.end()); } bool SpatExtent::compare(SpatExtent e, std::string oper, double tolerance) { if (!extent_operator(oper)) { return false; // not very useful } //double xr = (xmax - xmin) / tolerance; //double yr = (ymax - ymin) / tolerance; bool e1 = fabs(xmax - e.xmax) <= tolerance; bool e2 = fabs(xmin - e.xmin) <= tolerance; bool e3 = fabs(ymax - e.ymax) <= tolerance; bool e4 = fabs(ymin - e.ymin) <= tolerance; bool equal = (e1 && e2 && e3 && e4); if (oper == "==") { return equal; } else if (oper == "!=") { return (!equal); } if (oper == "<" || oper == "<=") { bool c1 = xmax < e.xmax; bool c2 = xmin > e.xmin; bool c3 = ymax < e.ymax; bool c4 = ymin > e.ymin; bool smaller = (c1 && c2 && c3 && c4); if (oper == "<") { return smaller; } else { return (equal || smaller); } } if (oper == ">" || oper == ">=") { bool c1 = xmax > e.xmax; bool c2 = xmin < e.xmin; bool c3 = ymax > e.ymax; bool c4 = ymin < e.ymin; bool larger = (c1 && c2 && c3 && c4); if (oper == ">") { return larger; } else { return (equal || larger); } } return false; } SpatExtent SpatExtent::round(int n) { double xn = roundn(xmin, n); double xx = roundn(xmax, n); double yn = roundn(ymin, n); double yx = roundn(ymax, n); SpatExtent e(xn, xx, yn, yx); return e; } SpatExtent SpatExtent::floor() { double xn = std::floor(xmin); double xx = std::ceil(xmax); double yn = std::floor(ymin); double yx = std::ceil(ymax); SpatExtent e(xn, xx, yn, yx); return e; } SpatExtent SpatExtent::ceil() { double xn = std::ceil(xmin); double xx = std::floor(xmax); double yn = std::ceil(ymin); double yx = std::floor(ymax); SpatExtent e(xn, xx, yn, yx); return e; } SpatExtent SpatRaster::getExtent() { if (source.size() > 0) { return source[0].extent; } else { SpatExtent e; return e; } } void SpatRaster::setExtent(SpatExtent e) { for (size_t i=0; i res = resolution(); double xrs = res[0]; double yrs = res[1]; unsigned nc = std::max(1.0, round( (ext.xmax - ext.xmin) / xrs )); unsigned nr = std::max(1.0, round( (ext.ymax - ext.ymin) / yrs )); source[0].ncol = nc; source[0].nrow = nr; ext.xmax = ext.xmin + nc * xrs; ext.ymax = ext.ymin + nr * yrs; source[0].extent = ext; } for (size_t i=0; i e = asVector(); if (d == 0) { SpatExtent out = *this; return(out); } d = d < 0 ? -d : d; for (size_t i=0; i<4; i++) { double x = d * trunc(e[i] / d); if ((i == 0) | (i == 2)) { if (x > e[i]) { x -= d; } } else { if (x < e[i]) { x += d; } } e[i] = x; } SpatExtent out(e[0], e[1], e[2], e[3]); return(out) ; } SpatExtent SpatRaster::align(SpatExtent e, std::string snap) { snap = is_in_set_default(snap, std::vector {"near", "in", "out"}, "near", true); std::vector res = resolution(); std::vector orig = origin(); // snap points to cell boundaries double xmn, xmx, ymn, ymx; if (snap == "near") { xmn = round((e.xmin-orig[0]) / res[0]) * res[0] + orig[0]; xmx = round((e.xmax-orig[0]) / res[0]) * res[0] + orig[0]; ymn = round((e.ymin-orig[1]) / res[1]) * res[1] + orig[1]; ymx = round((e.ymax-orig[1]) / res[1]) * res[1] + orig[1]; } else if (snap == "out") { xmn = std::floor((e.xmin-orig[0]) / res[0]) * res[0] + orig[0]; xmx = std::ceil((e.xmax-orig[0]) / res[0]) * res[0] + orig[0]; ymn = std::floor((e.ymin-orig[1]) / res[1]) * res[1] + orig[1]; ymx = std::ceil((e.ymax-orig[1]) / res[1]) * res[1] + orig[1]; } else { //if (snap == "in") { xmn = std::ceil((e.xmin-orig[0]) / res[0]) * res[0] + orig[0]; xmx = std::floor((e.xmax-orig[0]) / res[0]) * res[0] + orig[0]; ymn = std::ceil((e.ymin-orig[1]) / res[1]) * res[1] + orig[1]; ymx = std::floor((e.ymax-orig[1]) / res[1]) * res[1] + orig[1]; if (xmn > xmx) std::swap(xmn, xmx); if (ymn > ymx) std::swap(ymn, ymx); } if (xmn == xmx) { if (xmn < e.xmin) { xmx = xmx + res[0]; } else { xmn = xmn - res[0]; } } if (ymn == ymx) { if (ymn < e.ymin) { ymx = ymx + res[1]; } else { ymn = ymn - res[1]; } } return SpatExtent(xmn, xmx, ymn, ymx); } std::vector SpatRaster::origin() { std::vector r = resolution(); SpatExtent extent = getExtent(); double x = extent.xmin - r[0] * (round(extent.xmin / r[0])); double y = extent.ymax - r[1] * (round(extent.ymax / r[1])); if (is_equal((r[0] + x), abs(x))) { x = fabs(x); } if (is_equal((r[1] + y), abs(y))) { y = fabs(y); } std::vector out {x, y}; return out; } bool SpatRaster::compare_geom(SpatRaster x, bool lyrs, bool crs, double tol, bool warncrs, bool ext, bool rowcol, bool res) { tol = tol < 0 ? 0 : tol; if (ext) { SpatExtent extent = getExtent(); double res = std::max(xres(), yres()); if (extent.compare(x.getExtent(), "!=", tol * res)) { setError("extents do not match"); return false; } } if (rowcol) { if (! ((nrow() == x.nrow()) && (ncol() == x.ncol())) ) { setError("number of rows and/or columns do not match"); return false; } } if (res) { if (! ((is_equal_relative(x.xres(), xres(), 0.0001)) & (is_equal_relative(x.yres(), yres(), 0.0001)))) { setError("resolution does not match"); return false; } } if (lyrs) { if (!(nlyr() == x.nlyr())) { setError("number of layers does not match"); return false; } } if (crs) { if (!source[0].srs.is_equal(x.source[0].srs)) { if (warncrs) { addWarning("SRS do not match"); } else { setError("SRS do not match"); return false; } } } return true; } terra/src/gdal_multidimensional.cpp0000644000175000017500000001660614201035750017366 0ustar nileshnilesh #include "spatRaster.h" /* #if GDAL_VERSION_MAJOR >= 3 && GDAL_VERSION_MINOR >= 1 #include "proj.h" #include "ogr_spatialref.h" #include "gdal_priv.h" #include "gdal.h" #include "crs.h" #include "string_utils.h" bool SpatRaster::constructFromFileMulti(std::string fname, std::string sub, std::vector xyz) { if (xyz.size() != 3) { setError("you must supply three dimension indices"); return false; } auto poDataset = std::unique_ptr( GDALDataset::Open(fname.c_str(), GDAL_OF_MULTIDIM_RASTER )); if( !poDataset ) { setError("not a good dataset"); return false; } auto poRootGroup = poDataset->GetRootGroup(); if( !poRootGroup ) { setError("no roots"); return false; } bool warngroup = false; std::vector gnames; if (sub == "") { char** papszOptions = NULL; gnames = poRootGroup->GetMDArrayNames(papszOptions); CSLDestroy(papszOptions); sub = gnames[0]; if (gnames.size() > 1) warngroup = true; } auto poVar = poRootGroup->OpenMDArray(sub.c_str()); if( !poVar ) { setError("cannot find: " + sub); return false; } SpatRasterSource s; std::string wkt = ""; std::shared_ptr srs = poVar->GetSpatialRef(); if (srs != NULL) { char *cp; const char *options[3] = { "MULTILINE=YES", "FORMAT=WKT2", NULL }; OGRErr err = srs->exportToWkt(&cp, options); if (err == OGRERR_NONE) { wkt = std::string(cp); } CPLFree(cp); } std::string msg; if (!s.srs.set({wkt}, msg)) { addWarning(msg); } std::vector dimcount; std::vector dimnames; std::vector dim_start, dim_end; GDALExtendedDataTypeH hDT = GDALExtendedDataTypeCreate(GDT_Float64); for ( const auto &poDim: poVar->GetDimensions() ) { dimcount.push_back(static_cast(poDim->GetSize())); dimnames.push_back(static_cast(poDim->GetName())); std::vector count = {dimcount[dimcount.size()-1]}; std::vector vals(count[0]); const auto indvar = poDim->GetIndexingVariable(); indvar->Read( std::vector{0}.data(), count.data(), nullptr, nullptr, GDALExtendedDataType::Create(GDT_Float64), &vals[0]); // to do: check for equal spacing if x or y dim dim_start.push_back(vals[0]); dim_end.push_back(vals[vals.size()-1]); Rcpp::Rcout << vals[0] << " - " << vals[vals.size()-1] << std::endl; } GDALExtendedDataTypeRelease(hDT); s.m_ndims = dimcount.size(); if (warngroup) { std::string gn = ""; for (size_t i=0; iGetAttribute("long_name")->ReadAsString(); s.m_hasNA = false; double NAval = poVar->GetNoDataValueAsDouble(&s.m_hasNA); if (s.m_hasNA) { s.m_missing_value = NAval; } SpatExtent e; if (xyz[0] < s.m_ndims) { s.nrow = dimcount[xyz[0]]; s.m_dimnames.push_back(dimnames[xyz[0]]); double res = (dim_start[xyz[0]] - dim_end[xyz[0]]) / (s.nrow-1); e.ymax = dim_start[xyz[0]] + 0.5 * res; e.ymin = dim_end[xyz[0]] - 0.5 * res; } else { setError("the second dimension is not valid"); return false; } if (xyz[1] < s.m_ndims) { s.ncol = dimcount[xyz[1]]; s.m_dimnames.push_back(dimnames[xyz[1]]); double res = (dim_end[xyz[1]] - dim_start[xyz[1]]) / (s.ncol-1); e.xmin = dim_start[xyz[1]] - 0.5 * res; e.xmax = dim_end[xyz[1]] + 0.5 * res; } else { setError("the first dimension is not valid"); return false; } if (s.m_ndims > 2) { if (xyz[2] < s.m_ndims) { s.nlyr = dimcount[xyz[2]]; s.m_dimnames.push_back(dimnames[xyz[2]]); } else { setError("the third dimension is not valid"); return false; } } s.m_dims = xyz; s.extent = e; if (s.m_ndims > 3) { for (size_t i=0; i(s.nlyr, poVar->GetUnit()); s.multidim = true; // layer names // time // extent s.m_counts = dimcount; setSource(s); for (size_t i=0; i &out, size_t src, size_t row, size_t nrows, size_t col, size_t ncols) { std::vector offset(source[src].m_ndims, 0); std::vector dims = source[src].m_dims; offset[source[src].m_dims[0]] = row; offset[source[src].m_dims[1]] = col; offset[source[src].m_dims[2]] = 0; // std::vector count = source[src].m_counts; std::vector count(source[src].m_ndims, 1); count[source[src].m_dims[0]] = nrows; count[source[src].m_dims[1]] = ncols; count[source[src].m_dims[2]] = nlyr(); size_t n=1; for (size_t i=0; i temp; temp.resize(n); GDALMDArrayRead(source[src].gdalmdarray, &offset[0], &count[0], NULL, // step: defaults to 1,1,1 NULL, // stride: default to row-major convention hDT, &temp[0], NULL, // array start. Omitted 0 // array size in bytes. Omitted ); GDALExtendedDataTypeRelease(hDT); size_t nc = ncell(); size_t nl = nlyr(); out.resize(0); out.reserve(n); for (size_t i=0; i xyz) { setError("multidim is not supported by GDAL < 3.1"); return false; } bool SpatRaster::readStartMulti(unsigned src) { setError("multidim is not supported by GDAL < 3.1"); return false; } bool SpatRaster::readStopMulti(unsigned src) { setError("multidim is not supported by GDAL < 3.1"); return false; } bool SpatRaster::readValuesMulti(std::vector &out, size_t src, size_t row, size_t nrows, size_t col, size_t ncols) { setError("multidim is not supported by GDAL < 3.1"); return false; } /* #endif */ terra/src/gdalio.cpp0000644000175000017500000007217014201035750014257 0ustar nileshnilesh#include #include "ogr_spatialref.h" #include "spatRaster.h" #include "string_utils.h" #include "file_utils.h" #include "crs.h" //#include //#include #include "cpl_port.h" #include "cpl_conv.h" // CPLFree() //#include "gdal_version.h" void getGDALdriver(std::string &filename, std::string &driver) { lrtrim(filename); lrtrim(driver); if (driver != "") { if (driver == "RST") { filename = noext(filename) + ".rst"; } return; } std::string ext = getFileExt(filename); lowercase(ext); std::unordered_map drivers = { {".tif","GTiff"}, {".tiff","GTiff"}, {".nc","netCDF"}, {".cdf","netCDF"}, {".gpkg","GPKG"}, {".img","HFA"}, {".ige","HFA"}, {".bmp","BMP"}, {".flt","EHdr"}, {".grd","RRASTER"}, {".gri","RRASTER"}, {".sgrd","SAGA"}, {".sdat","SAGA"}, {".rst","RST"}, {".rdc","RST"}, {".envi","ENVI"}, {".asc","AAIGrid"}, {".bmp","BMP"}, // {".jpg","JPEG"}, or JPEG2000? {".png","PNG"}, {".gif","GIF"}, }; auto i = drivers.find(ext); if (i != drivers.end()) { driver = i->second; } } /* std::string sectostr(int x) { char buffer[20]; time_t now = x; tm *utc = gmtime(&now); strftime (buffer, 20, "%Y-%m-%d %H:%M:%S", utc); std::string s = buffer; return s; } */ GDALDataset* openGDAL(std::string filename, unsigned OpenFlag, std::vector open_options) { //std::vector oo_char = string_to_charpnt(openopts); // open options //poDataset = static_cast(GDALOpenEx( filename.c_str(), OpenFlag, NULL, oo_char.data(), NULL )); char ** openops = NULL; // for ncdf // openops = CSLSetNameValue(openops, "@HONOUR_VALID_RANGE", "NO"); for (size_t i=0; i opt = strsplit(open_options[i], "="); if (opt.size() == 2) { // Rcpp::Rcout << opt[0] << "=" << opt[1] << std::endl; openops = CSLSetNameValue(openops, opt[0].c_str(), opt[1].c_str()); } } GDALDataset *poDataset = static_cast(GDALOpenEx( filename.c_str(), OpenFlag, NULL, openops, NULL)); CSLDestroy(openops); return poDataset; } std::vector get_metadata(std::string filename) { std::vector out; std::vector ops; GDALDataset *poDataset = openGDAL(filename, GDAL_OF_RASTER | GDAL_OF_READONLY, ops); if( poDataset == NULL ) { return out; } char **m = poDataset->GetMetadata(); if (m != NULL) { // needed while (*m != nullptr) { out.push_back(*m++); } } GDALClose( (GDALDatasetH) poDataset ); return out; } std::vector get_metadata_sds(std::string filename) { std::vector meta; GDALDataset *poDataset = openGDAL(filename, GDAL_OF_RASTER | GDAL_OF_READONLY, meta); if( poDataset == NULL ) { return meta; } char **metadata = poDataset->GetMetadata("SUBDATASETS"); if (metadata != NULL) { for (size_t i=0; metadata[i] != NULL; i++) { meta.push_back(metadata[i]); } } GDALClose( (GDALDatasetH) poDataset ); return meta; } std::vector> parse_metadata_sds(std::vector meta) { std::vector name, var, desc, nr, nc, nl; std::string ndelim = "NAME="; std::string ddelim = "DESC="; for (size_t i=0; i d = strsplit(dims, "x"); if (d.size() < 2) { nl.push_back("0"); nr.push_back("0"); nc.push_back("0"); } else if (d.size() == 2) { nl.push_back("1"); nr.push_back(d[0]); nc.push_back(d[1]); } else { size_t ds = d.size()-1; size_t nls = 0; try { nls = stoi(d[ds-2]); for (size_t i=0; i<(ds-2); i++) { nls *= stoi(d[i]); } } catch(...) {} nl.push_back(std::to_string(nls)); nr.push_back(d[ds-1]); nc.push_back(d[ds]); } //desc.push_back(std::string(pos, s.size())); s = s.substr(pos+2, s.size()); pos = s.find(" "); s = s.substr(0, pos); desc.push_back(s); // nr.push_back( std::to_string(sub.nrow())); // nc.push_back(std::to_string(sub.ncol())); // nl.push_back(std::to_string(sub.nlyr())); } else { desc.push_back(""); } } } std::vector> out(6); out[0] = name; out[1] = var; out[2] = desc; out[3] = nr; out[4] = nc; out[5] = nl; return out; } std::vector> sdinfo(std::string fname) { std::vector> out(6); std::vector ops; GDALDataset *poDataset = openGDAL(fname, GDAL_OF_RASTER | GDAL_OF_READONLY, ops); if( poDataset == NULL ) { if (!file_exists(fname)) { out[0] = std::vector {"no such file"}; } else { out[0] = std::vector {"cannot open file"}; } return out; } char **metadata = poDataset->GetMetadata("SUBDATASETS"); if (metadata == NULL) { out[0] = std::vector {"no subdatasets"}; GDALClose( (GDALDatasetH) poDataset ); return out; } std::vector meta; for (size_t i=0; metadata[i] != NULL; i++) { meta.push_back(metadata[i]); } if (meta.size() == 0) { GDALClose( (GDALDatasetH) poDataset ); out[0] = std::vector {"no subdatasets"}; return out; } SpatRaster sub; std::vector name, var, desc, nr, nc, nl; std::string ndelim = "NAME="; std::string ddelim = "DESC="; for (size_t i=0; i filenames, SpatOptions &opt) { SpatRaster out; out.setError( "GDAL version >= 2.1 required for vrt"); return out; } std::string gdalinfo(std::string filename, std::vector options, std::vector oo) { std::string out = "GDAL version >= 2.1 required for gdalinfo"; return out; } #else # include "gdal_utils.h" // requires >= 2.1 SpatRaster SpatRaster::make_vrt(std::vector filenames, SpatOptions &opt) { SpatRaster out; std::string outfile = opt.get_filename(); if (outfile == "") { outfile = tempFile(opt.get_tempdir(), opt.pid, ".vrt"); } else if (file_exists(outfile) & (!opt.get_overwrite())) { out.setError("output file exists. You can use 'overwrite=TRUE' to overwrite it"); return(out); } std::vector tiles; std::vector ops; for (std::string& f : filenames) { GDALDataset *poDataset = openGDAL(f, GDAL_OF_RASTER | GDAL_OF_READONLY, ops); if( poDataset == NULL ) { for (size_t j= 0; j options, std::vector openopts) { // adapted from the 'sf' package by Edzer Pebesma et al std::string out = ""; char ** opops = NULL; for (size_t i=0; i opt = strsplit(openopts[i], "="); if (opt.size() == 2) { opops = CSLSetNameValue(opops, opt[0].c_str(), opt[1].c_str()); } } GDALDatasetH ds = GDALOpenEx(filename.c_str(), GA_ReadOnly, NULL, opops, NULL); //if (opops != NULL) CSLDestroy(opops); if (ds == NULL) return out; std::vector options_char = string_to_charpnt(options); GDALInfoOptions* opt = GDALInfoOptionsNew(options_char.data(), NULL); char *val = GDALInfo(ds, opt); out = val; CPLFree(val); GDALClose(ds); GDALInfoOptionsFree(opt); return out; } #endif bool getNAvalue(GDALDataType gdt, double & naval) { if (gdt == GDT_Float32) { naval = NAN; } else if (gdt == GDT_Int32) { naval = INT32_MIN; } else if (gdt == GDT_Float64) { naval = NAN; } else if (gdt == GDT_Int16) { naval = INT16_MIN; } else if (gdt == GDT_UInt32) { naval = UINT32_MAX; } else if (gdt == GDT_UInt16) { naval = UINT16_MAX; } else if (gdt == GDT_Byte) { naval = 255; } else { naval = NAN; return false; } return true; } bool getGDALDataType(std::string datatype, GDALDataType &gdt) { if (datatype=="FLT4S") { gdt = GDT_Float32; } else if (datatype == "INT4S") { gdt = GDT_Int32; } else if (datatype == "FLT8S") { gdt = GDT_Float64; } else if (datatype == "INT2S") { gdt = GDT_Int16; } else if (datatype == "INT4U") { gdt = GDT_UInt32; } else if (datatype == "INT2U") { gdt = GDT_UInt16; } else if (datatype == "INT1U") { gdt = GDT_Byte; } else { gdt = GDT_Float32; return false; } return true; } bool GDALsetSRS(GDALDatasetH &hDS, const std::string &crs) { OGRSpatialReferenceH hSRS = OSRNewSpatialReference( NULL ); OGRErr erro = OSRSetFromUserInput(hSRS, crs.c_str()); if (erro == 4) { return false ; } char *pszSRS_WKT = NULL; OSRExportToWkt( hSRS, &pszSRS_WKT ); OSRDestroySpatialReference( hSRS ); GDALSetProjection( hDS, pszSRS_WKT ); CPLFree( pszSRS_WKT ); return true; } bool SpatRaster::as_gdalvrt(GDALDatasetH &hVRT, SpatOptions &opt) { // all sources should be on disk GDALDriverH hDrv = GDALGetDriverByName("MEM"); hVRT = GDALCreate(hDrv, "", ncol(), nrow(), nlyr(), GDT_Float64, NULL); std::vector rs = resolution(); SpatExtent extent = getExtent(); double adfGeoTransform[6] = { extent.xmin, rs[0], 0, extent.ymax, 0, -1 * rs[1] }; GDALSetGeoTransform(hVRT, adfGeoTransform); if (!GDALsetSRS(hVRT, source[0].srs.wkt)) { addWarning("cannot set SRS"); } char** papszOptions = NULL; SpatRaster RS; GDALDatasetH DS; for (size_t i=0; i 1) & (src < 0)) { if (canProcessInMemory(opt)) { fromfile = false; } else { // make VRT setError("right now this method can only handle one file source at a time"); return false; } } if (fromfile) { std::string f; //if (source[src].parameters_changed) { // make a copy to get the write the new crs or extent // can we use a VRT instead? // f = tempFile(opt.get_tempdir(), ".tif"); // SpatRaster tmp(source[src]); // SpatOptions topt(opt); // topt.set_filenames({f}); // tmp.writeRaster(topt); //} else { f = source[src].filename; //} //hDS = GDALOpenShared(f.c_str(), GA_ReadOnly); if (update) { hDS = openGDAL(f, GDAL_OF_RASTER | GDAL_OF_UPDATE | GDAL_OF_SHARED, source[src].open_ops); /* if (hDS != NULL) { // for user-set extents std::vector rs = resolution(); SpatExtent extent = getExtent(); double adfGeoTransform[6] = { extent.xmin, rs[0], 0, extent.ymax, 0, -1 * rs[1] }; GDALSetGeoTransform(hDS, adfGeoTransform); } */ } else { hDS = openGDAL(f, GDAL_OF_RASTER | GDAL_OF_READONLY | GDAL_OF_SHARED, source[src].open_ops); } return (hDS != NULL); } else { // in memory bool hasval = source[isrc].hasValues; size_t nl; if (src < 0) { nl = nlyr(); } else { nl = source[src].layers.size(); } size_t ncls = nrow() * ncol(); GDALDriverH hDrv = GDALGetDriverByName("MEM"); /*https://gis.stackexchange.com/questions/196048/how-to-reuse-memory-pointer-of-gdal-memory-driver char **papszOptions = NULL; hDS = GDALCreate(hDrv, "", ncol(), nrow(), 0, GDT_Float64, papszOptions); if (hDS == NULL) return false; std::vector vals; for(size_t i=0; i(source[0].values.begin() +off, source[0].values.begin() +off+ncls); char szPtrValue[128] = { '\0' }; int nRet = CPLPrintPointer( szPtrValue, reinterpret_cast(&vals[0]), sizeof(szPtrValue) ); szPtrValue[nRet] = 0; papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szPtrValue); GDALAddBand(hDS, GDT_Float64, papszOptions); } CSLDestroy(papszOptions); */ size_t nr = nrow(); size_t nc = ncol(); hDS = GDALCreate(hDrv, "", nc, nr, nl, GDT_Float64, NULL); if (hDS == NULL) return false; std::vector rs = resolution(); SpatExtent extent = getExtent(); double adfGeoTransform[6] = { extent.xmin, rs[0], 0, extent.ymax, 0, -1 * rs[1] }; GDALSetGeoTransform(hDS, adfGeoTransform); if (!GDALsetSRS(hDS, source[0].srs.wkt)) { setError("cannot set SRS"); return false; } CPLErr err = CE_None; if (hasval) { std::vector nms; if (src < 0) { nms = getNames(); } else { nms = source[src].names; } std::vector vv, vals; if (src < 0) { vv = getValues(-1, opt); } else { if (!getValuesSource(src, vv)) { setError("cannot read from source"); return false; } } for (size_t i=0; i < nl; i++) { GDALRasterBandH hBand = GDALGetRasterBand(hDS, i+1); GDALSetRasterNoDataValue(hBand, NAN); GDALSetDescription(hBand, nms[i].c_str()); size_t offset = ncls * i; vals = std::vector(vv.begin() + offset, vv.begin() + offset+ncls); err = GDALRasterIO(hBand, GF_Write, 0, 0, nc, nr, &vals[0], nc, nr, GDT_Float64, 0, 0); if (err != CE_None) { return false; } } } } return true; } bool SpatRaster::from_gdalMEM(GDALDatasetH hDS, bool set_geometry, bool get_values) { if (set_geometry) { SpatRasterSource s; s.ncol = GDALGetRasterXSize( hDS ); s.nrow = GDALGetRasterYSize( hDS ); s.nlyr = GDALGetRasterCount( hDS ); double adfGeoTransform[6]; if( GDALGetGeoTransform( hDS, adfGeoTransform ) != CE_None ) { setError("Cannot get geotransform"); return false; } double xmin = adfGeoTransform[0]; double xmax = xmin + adfGeoTransform[1] * s.ncol; double ymax = adfGeoTransform[3]; double ymin = ymax + s.nrow * adfGeoTransform[5]; s.extent = SpatExtent(xmin, xmax, ymin, ymax); s.memory = true; s.names = source[0].names; std::string wkt; #if GDAL_VERSION_MAJOR >= 3 std::string errmsg; OGRSpatialReferenceH srs = GDALGetSpatialRef( hDS ); if (srs == NULL) { return false; } const char *options[3] = { "MULTILINE=YES", "FORMAT=WKT2", NULL }; char *cp; OGRErr err = OSRExportToWktEx(srs, &cp, options); if (is_ogr_error(err, errmsg)) { CPLFree(cp); return false; } wkt = std::string(cp); CPLFree(cp); #else const char *pszSrc = GDALGetProjectionRef( hDS ); if (pszSrc != NULL) { wkt = std::string(pszSrc); } else { return false; } //OGRSpatialReferenceH srs = GDALGetProjectionRef( hDS ); //OGRSpatialReference oSRS(poDataset->GetProjectionRef()); //OGRErr err = oSRS.exportToPrettyWkt(&cp); #endif std::string msg; if (!s.srs.set({wkt}, msg)) { setError(msg); return false; } setSource(s); } if (get_values) { source[0].values.resize(0); source[0].values.reserve(ncell() * nlyr()); CPLErr err = CE_None; int hasNA; size_t nl = nlyr(); for (size_t i=0; i < nl; i++) { GDALRasterBandH hBand = GDALGetRasterBand(hDS, i+1); std::vector lyrout( ncell() ); err = GDALRasterIO(hBand, GF_Read, 0, 0, ncol(), nrow(), &lyrout[0], ncol(), nrow(), GDT_Float64, 0, 0); if (err != CE_None ) { setError("CE_None"); return false; } //double naflag = -3.4e+38; double naflag = GDALGetRasterNoDataValue(hBand, &hasNA); if (hasNA && (!std::isnan(naflag))) { if (naflag < -3.4e+37) { naflag = -3.4e+37; for (size_t i=0; i gdal_options) { char ** gdalops = NULL; if (driver == "GTiff") { bool lzw = true; bool compressed = true; for (size_t i=0; i 4194304000)) { bool big = true; for (size_t i=0; i gopt = strsplit(gdal_options[i], "="); if (gopt.size() == 2) { gdalops = CSLSetNameValue(gdalops, gopt[0].c_str(), gopt[1].c_str() ); } } return gdalops; } bool SpatRaster::create_gdalDS(GDALDatasetH &hDS, std::string filename, std::string driver, bool fill, double fillvalue, std::vector has_so, std::vector scale, std::vector offset, SpatOptions& opt) { has_so.resize(nlyr(), false); const char *pszFormat = driver.c_str(); GDALDriverH hDrv = GDALGetDriverByName(pszFormat); double naflag = opt.NAflag; //NAN; GDALDataType gdt; char **papszOptions = NULL; if (driver != "MEM") { std::string datatype = opt.get_datatype(); if (!getGDALDataType(datatype, gdt)) { addWarning("unknown datatype = " + datatype); getGDALDataType("FLT4S", gdt); } int dsize = std::stoi(datatype.substr(3,1)); GIntBig diskNeeded = ncell() * nlyr() * dsize; std::string dname = dirname(filename); GIntBig diskAvailable = VSIGetDiskFreeSpace(dname.c_str()); if ((diskAvailable > -1) && (diskAvailable < diskNeeded)) { setError("insufficient disk space (perhaps from temporary files?)"); return(false); } papszOptions = set_GDAL_options(driver, diskNeeded, false, opt.gdal_options); if (datatype == "INT4S") { naflag = INT32_MIN; //-2147483648; } else if (datatype == "INT2S") { naflag = INT16_MIN; } else if (datatype == "INT4U") { naflag = UINT32_MAX; } else if (datatype == "INT2U") { naflag = UINT16_MAX; } else if (datatype == "INT1U") { naflag = 255; // ?; } } else { getGDALDataType(opt.get_datatype(), gdt); } const char *pszFilename = filename.c_str(); hDS = GDALCreate(hDrv, pszFilename, ncol(), nrow(), nlyr(), gdt, papszOptions ); CSLDestroy( papszOptions ); std::vector nms = getNames(); std::vector hasCats = hasCategories(); for (size_t i=0; i < nlyr(); i++) { GDALRasterBandH hBand = GDALGetRasterBand(hDS, i+1); GDALSetDescription(hBand, nms[i].c_str()); GDALSetRasterNoDataValue(hBand, naflag); //GDALSetRasterNoDataValue(hBand, -3.4e+38); if (fill) GDALFillRaster(hBand, fillvalue, 0); if (has_so[i]) { GDALSetRasterOffset(hBand, offset[i]); GDALSetRasterScale(hBand, scale[i]); } if (hasCats[i]) { std::vector cats = getLabels(i); char **names = NULL; for (size_t j = 0; j < cats.size(); j++) { names = CSLAddString(names, cats[j].c_str()); } CPLErr err = GDALSetRasterCategoryNames(hBand, names); if (err != CE_None) { addWarning("could not write categories"); } CSLDestroy( names ); } } std::vector rs = resolution(); SpatExtent e = getExtent(); double adfGeoTransform[6] = { e.xmin, rs[0], 0, e.ymax, 0, -1 * rs[1] }; GDALSetGeoTransform( hDS, adfGeoTransform); std::string wkt = getSRS("wkt"); if (wkt != "") { OGRSpatialReferenceH hSRS = OSRNewSpatialReference( NULL ); OGRErr erro = OSRSetFromUserInput(hSRS, wkt.c_str()); if (erro == 4) { setError("CRS failure"); OSRDestroySpatialReference( hSRS ); return false; } char *pszSRS_WKT = NULL; OSRExportToWkt( hSRS, &pszSRS_WKT ); GDALSetProjection( hDS, pszSRS_WKT ); CPLFree(pszSRS_WKT); OSRDestroySpatialReference( hSRS ); } return true; } /* bool SpatRaster::setValuesMEM(GDALDatasetH hDS, bool set_geometry) { if (set_geometry) { SpatRasterSource s; s.ncol = GDALGetRasterXSize( hDS ); s.nrow = GDALGetRasterYSize( hDS ); s.nlyr = GDALGetRasterCount( hDS ); double adfGeoTransform[6]; if( GDALGetGeoTransform( hDS, adfGeoTransform ) != CE_None ) { setError("Cannot get geotransform"); return false; } double xmin = adfGeoTransform[0]; double xmax = xmin + adfGeoTransform[1] * s.ncol; double ymax = adfGeoTransform[3]; double ymin = ymax + s.nrow * adfGeoTransform[5]; s.extent = SpatExtent(xmin, xmax, ymin, ymax); s.driver = "memory"; s.names = source[0].names; setSource(s); OGRSpatialReferenceH srs = GDALGetSpatialRef( hDS ); char *cp; const char *options[3] = { "MULTILINE=YES", "FORMAT=WKT2", NULL }; OGRErr err = OSRExportToWktEx(srs, &cp, options); std::string errmsg; if (is_ogr_error(err, errmsg)) { CPLFree(cp); return false; } std::string wkt = std::string(cp); CPLFree(cp); std::string msg; if (!s.srs.set({wkt}, msg)) { setError(msg); return false; } } source[0].values.reserve(ncell() * nlyr()); CPLErr err = CE_None; int hasNA; for (size_t i=0; i < nlyr(); i++) { GDALRasterBandH hBand = GDALGetRasterBand(hDS, i+1); std::vector lyrout( ncell() ); err = GDALRasterIO(hBand, GF_Read, 0, 0, ncol(), nrow(), &lyrout[0], ncol(), nrow(), GDT_Float64, 0, 0); if (err != CE_None ) { setError("CE_None"); return false; } //double naflag = -3.4e+38; double naflag = GDALGetRasterNoDataValue(hBand, &hasNA); if (hasNA) std::replace(lyrout.begin(), lyrout.end(), naflag, (double) NAN); source[0].values.insert(source[0].values.end(), lyrout.begin(), lyrout.end()); } source[0].hasValues = TRUE; source[0].memory = TRUE; source[0].driver = "memory"; source[0].setRange(); return true; } bool gdal_ds_create(SpatRaster x, GDALDatasetH &hDS, std::string filename, std::string driver, std::vector foptions, bool fill, std::string &msg) { msg = ""; char **papszOptions = NULL; for (size_t i=0; i < foptions.size(); i++) { std::vector wopt = strsplit(foptions[i], "="); if (wopt.size() == 2) { papszOptions = CSLSetNameValue( papszOptions, wopt[0].c_str(), wopt[1].c_str() ); } } const char *pszFormat = driver.c_str(); GDALDriverH hDrv = GDALGetDriverByName(pszFormat); const char *pszFilename = filename.c_str(); hDS = GDALCreate(hDrv, pszFilename, x.ncol(), x.nrow(), x.nlyr(), GDT_Float64, papszOptions ); CSLDestroy( papszOptions ); GDALRasterBandH hBand; std::vector nms = x.getNames(); for (size_t i=0; i < x.nlyr(); i++) { hBand = GDALGetRasterBand(hDS, i+1); GDALSetDescription(hBand, nms[i].c_str()); GDALSetRasterNoDataValue(hBand, NAN); //GDALSetRasterNoDataValue(hBand, -3.4e+38); if (fill) GDALFillRaster(hBand, NAN, 0); } std::vector rs = x.resolution(); SpatExtent e = x.getExtent(); double adfGeoTransform[6] = { e.xmin, rs[0], 0, e.ymax, 0, -1 * rs[1] }; GDALSetGeoTransform( hDS, adfGeoTransform); OGRSpatialReferenceH hSRS = OSRNewSpatialReference( NULL ); std::vector srs = x.getSRS(); std::string wkt = srs[1]; OGRErr erro = OSRSetFromUserInput(hSRS, wkt.c_str()); if (erro == 4) { msg = "CRS failure"; OSRDestroySpatialReference( hSRS ); return false; } char *pszSRS_WKT = NULL; OSRExportToWkt( hSRS, &pszSRS_WKT ); GDALSetProjection( hDS, pszSRS_WKT ); CPLFree(pszSRS_WKT); OSRDestroySpatialReference( hSRS ); return true; } bool SpatRaster::open_gdal(GDALDatasetH &hDS) { // needs to loop over sources. thus should vector of GDALDatasetH // for now just doing the first if (!source[0].hasValues) { return false; } else if (source[0].driver == "gdal") { std::string f = source[0].filename; hDS = GDALOpen(f.c_str(), GA_ReadOnly); return(hDS != NULL); } else { // in memory size_t nl = nlyr(); size_t ncls = nrow() * ncol(); GDALDriverH hDrv = GDALGetDriverByName("MEM"); //https://gis.stackexchange.com/questions/196048/how-to-reuse-memory-pointer-of-gdal-memory-driver // char **papszOptions = NULL; // hDS = GDALCreate(hDrv, "", ncol(), nrow(), 0, GDT_Float64, papszOptions); // if (hDS == NULL) return false; // std::vector vals; // for(size_t i=0; i(source[0].values.begin() +off, source[0].values.begin() +off+ncls); // char szPtrValue[128] = { '\0' }; // int nRet = CPLPrintPointer( szPtrValue, reinterpret_cast(&vals[0]), sizeof(szPtrValue) ); // szPtrValue[nRet] = 0; // papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szPtrValue); // GDALAddBand(hDS, GDT_Float64, papszOptions); // } // CSLDestroy(papszOptions); size_t nr = nrow(); size_t nc = ncol(); hDS = GDALCreate(hDrv, "", nc, nr, nl, GDT_Float64, NULL); if (hDS == NULL) return false; std::vector rs = resolution(); double adfGeoTransform[6] = { extent.xmin, rs[0], 0, extent.ymax, 0, -1 * rs[1] }; GDALSetGeoTransform(hDS, adfGeoTransform); OGRSpatialReferenceH hSRS = OSRNewSpatialReference( NULL ); std::string crs = srs.wkt; OGRErr erro = OSRSetFromUserInput(hSRS, crs.c_str()); if (erro == 4) { setError("CRS failure"); return false ; } char *pszSRS_WKT = NULL; OSRExportToWkt( hSRS, &pszSRS_WKT ); OSRDestroySpatialReference( hSRS ); GDALSetProjection( hDS, pszSRS_WKT ); CPLFree( pszSRS_WKT ); CPLErr err = CE_None; std::vector vals; std::vector nms = getNames(); for (size_t i=0; i < nl; i++) { GDALRasterBandH hBand = GDALGetRasterBand(hDS, i+1); GDALSetRasterNoDataValue(hBand, NAN); GDALSetDescription(hBand, nms[i].c_str()); size_t offset = ncls * i; vals = std::vector(source[0].values.begin() + offset, source[0].values.begin() + offset + ncls); err = GDALRasterIO(hBand, GF_Write, 0, 0, nc, nr, &vals[0], nc, nr, GDT_Float64, 0, 0 ); if (err != CE_None) { return false; } } } return true; } */ terra/src/gdalio.h0000644000175000017500000000143214201035750013715 0ustar nileshnileshbool getGDALDataType(std::string datatype, GDALDataType &gdt); std::string gdalinfo(std::string filename, std::vector options, std::vector openopts); std::vector> sdinfo(std::string fname); std::vector get_metadata(std::string filename); std::vector get_metadata_sds(std::string filename); std::vector> parse_metadata_sds(std::vector meta); void getGDALdriver(std::string &filename, std::string &driver); bool getNAvalue(GDALDataType gdt, double & naval); GDALDataset* openGDAL(std::string filename, unsigned OpenFlag, std::vector open_options); char ** set_GDAL_options(std::string driver, double diskNeeded, bool writeRGB, std::vector gdal_options); terra/src/RcppExports.cpp0000644000175000017500000004155714201035750015316 0ustar nileshnilesh// Generated by using Rcpp::compileAttributes() -> do not edit by hand // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 #include using namespace Rcpp; #ifdef RCPP_USE_GLOBAL_ROSTREAM Rcpp::Rostream& Rcpp::Rcout = Rcpp::Rcpp_cout_get(); Rcpp::Rostream& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get(); #endif // proj_version std::string proj_version(); RcppExport SEXP _terra_proj_version() { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; rcpp_result_gen = Rcpp::wrap(proj_version()); return rcpp_result_gen; END_RCPP } // hex2rgb std::vector hex2rgb(std::string s); RcppExport SEXP _terra_hex2rgb(SEXP sSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::string >::type s(sSEXP); rcpp_result_gen = Rcpp::wrap(hex2rgb(s)); return rcpp_result_gen; END_RCPP } // rgb2hex std::string rgb2hex(std::vector x); RcppExport SEXP _terra_rgb2hex(SEXP xSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::vector >::type x(xSEXP); rcpp_result_gen = Rcpp::wrap(rgb2hex(x)); return rcpp_result_gen; END_RCPP } // sameSRS bool sameSRS(std::string x, std::string y); RcppExport SEXP _terra_sameSRS(SEXP xSEXP, SEXP ySEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::string >::type x(xSEXP); Rcpp::traits::input_parameter< std::string >::type y(ySEXP); rcpp_result_gen = Rcpp::wrap(sameSRS(x, y)); return rcpp_result_gen; END_RCPP } // getCRSname std::vector getCRSname(std::string s); RcppExport SEXP _terra_getCRSname(SEXP sSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::string >::type s(sSEXP); rcpp_result_gen = Rcpp::wrap(getCRSname(s)); return rcpp_result_gen; END_RCPP } // getLinearUnits double getLinearUnits(std::string s); RcppExport SEXP _terra_getLinearUnits(SEXP sSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::string >::type s(sSEXP); rcpp_result_gen = Rcpp::wrap(getLinearUnits(s)); return rcpp_result_gen; END_RCPP } // geotransform std::vector geotransform(std::string fname); RcppExport SEXP _terra_geotransform(SEXP fnameSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::string >::type fname(fnameSEXP); rcpp_result_gen = Rcpp::wrap(geotransform(fname)); return rcpp_result_gen; END_RCPP } // ginfo std::string ginfo(std::string filename, std::vector options, std::vector oo); RcppExport SEXP _terra_ginfo(SEXP filenameSEXP, SEXP optionsSEXP, SEXP ooSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::string >::type filename(filenameSEXP); Rcpp::traits::input_parameter< std::vector >::type options(optionsSEXP); Rcpp::traits::input_parameter< std::vector >::type oo(ooSEXP); rcpp_result_gen = Rcpp::wrap(ginfo(filename, options, oo)); return rcpp_result_gen; END_RCPP } // sd_info std::vector> sd_info(std::string filename); RcppExport SEXP _terra_sd_info(SEXP filenameSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::string >::type filename(filenameSEXP); rcpp_result_gen = Rcpp::wrap(sd_info(filename)); return rcpp_result_gen; END_RCPP } // gdal_version std::string gdal_version(); RcppExport SEXP _terra_gdal_version() { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; rcpp_result_gen = Rcpp::wrap(gdal_version()); return rcpp_result_gen; END_RCPP } // geos_version std::string geos_version(bool runtime, bool capi); RcppExport SEXP _terra_geos_version(SEXP runtimeSEXP, SEXP capiSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< bool >::type runtime(runtimeSEXP); Rcpp::traits::input_parameter< bool >::type capi(capiSEXP); rcpp_result_gen = Rcpp::wrap(geos_version(runtime, capi)); return rcpp_result_gen; END_RCPP } // metatdata std::vector metatdata(std::string filename); RcppExport SEXP _terra_metatdata(SEXP filenameSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::string >::type filename(filenameSEXP); rcpp_result_gen = Rcpp::wrap(metatdata(filename)); return rcpp_result_gen; END_RCPP } // sdsmetatdata std::vector sdsmetatdata(std::string filename); RcppExport SEXP _terra_sdsmetatdata(SEXP filenameSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::string >::type filename(filenameSEXP); rcpp_result_gen = Rcpp::wrap(sdsmetatdata(filename)); return rcpp_result_gen; END_RCPP } // sdsmetatdataparsed std::vector> sdsmetatdataparsed(std::string filename); RcppExport SEXP _terra_sdsmetatdataparsed(SEXP filenameSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::string >::type filename(filenameSEXP); rcpp_result_gen = Rcpp::wrap(sdsmetatdataparsed(filename)); return rcpp_result_gen; END_RCPP } // gdal_drivers std::vector> gdal_drivers(); RcppExport SEXP _terra_gdal_drivers() { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; rcpp_result_gen = Rcpp::wrap(gdal_drivers()); return rcpp_result_gen; END_RCPP } // set_gdal_warnings void set_gdal_warnings(int level); RcppExport SEXP _terra_set_gdal_warnings(SEXP levelSEXP) { BEGIN_RCPP Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< int >::type level(levelSEXP); set_gdal_warnings(level); return R_NilValue; END_RCPP } // gdal_init void gdal_init(std::string path); RcppExport SEXP _terra_gdal_init(SEXP pathSEXP) { BEGIN_RCPP Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::string >::type path(pathSEXP); gdal_init(path); return R_NilValue; END_RCPP } // percRank std::vector percRank(std::vector x, std::vector y, double minc, double maxc, int tail); RcppExport SEXP _terra_percRank(SEXP xSEXP, SEXP ySEXP, SEXP mincSEXP, SEXP maxcSEXP, SEXP tailSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::vector >::type x(xSEXP); Rcpp::traits::input_parameter< std::vector >::type y(ySEXP); Rcpp::traits::input_parameter< double >::type minc(mincSEXP); Rcpp::traits::input_parameter< double >::type maxc(maxcSEXP); Rcpp::traits::input_parameter< int >::type tail(tailSEXP); rcpp_result_gen = Rcpp::wrap(percRank(x, y, minc, maxc, tail)); return rcpp_result_gen; END_RCPP } // setGDALCacheSizeMB void setGDALCacheSizeMB(double x); RcppExport SEXP _terra_setGDALCacheSizeMB(SEXP xSEXP) { BEGIN_RCPP Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< double >::type x(xSEXP); setGDALCacheSizeMB(x); return R_NilValue; END_RCPP } // getGDALCacheSizeMB double getGDALCacheSizeMB(); RcppExport SEXP _terra_getGDALCacheSizeMB() { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; rcpp_result_gen = Rcpp::wrap(getGDALCacheSizeMB()); return rcpp_result_gen; END_RCPP } // get_proj_search_paths std::vector get_proj_search_paths(); RcppExport SEXP _terra_get_proj_search_paths() { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; rcpp_result_gen = Rcpp::wrap(get_proj_search_paths()); return rcpp_result_gen; END_RCPP } // set_proj_search_paths bool set_proj_search_paths(std::vector paths); RcppExport SEXP _terra_set_proj_search_paths(SEXP pathsSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< std::vector >::type paths(pathsSEXP); rcpp_result_gen = Rcpp::wrap(set_proj_search_paths(paths)); return rcpp_result_gen; END_RCPP } // PROJ_network std::string PROJ_network(bool enable, std::string url); RcppExport SEXP _terra_PROJ_network(SEXP enableSEXP, SEXP urlSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< bool >::type enable(enableSEXP); Rcpp::traits::input_parameter< std::string >::type url(urlSEXP); rcpp_result_gen = Rcpp::wrap(PROJ_network(enable, url)); return rcpp_result_gen; END_RCPP } // dist_lonlat double dist_lonlat(const double& lon1, const double& lat1, const double& lon2, const double& lat2); RcppExport SEXP _terra_dist_lonlat(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< const double& >::type lon1(lon1SEXP); Rcpp::traits::input_parameter< const double& >::type lat1(lat1SEXP); Rcpp::traits::input_parameter< const double& >::type lon2(lon2SEXP); Rcpp::traits::input_parameter< const double& >::type lat2(lat2SEXP); rcpp_result_gen = Rcpp::wrap(dist_lonlat(lon1, lat1, lon2, lat2)); return rcpp_result_gen; END_RCPP } // dir_lonlat double dir_lonlat(double lon1, double lat1, double lon2, double lat2); RcppExport SEXP _terra_dir_lonlat(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< double >::type lon1(lon1SEXP); Rcpp::traits::input_parameter< double >::type lat1(lat1SEXP); Rcpp::traits::input_parameter< double >::type lon2(lon2SEXP); Rcpp::traits::input_parameter< double >::type lat2(lat2SEXP); rcpp_result_gen = Rcpp::wrap(dir_lonlat(lon1, lat1, lon2, lat2)); return rcpp_result_gen; END_RCPP } // dist2track double dist2track(double lon1, double lat1, double lon2, double lat2, double plon, double plat, bool sign); RcppExport SEXP _terra_dist2track(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP plonSEXP, SEXP platSEXP, SEXP signSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< double >::type lon1(lon1SEXP); Rcpp::traits::input_parameter< double >::type lat1(lat1SEXP); Rcpp::traits::input_parameter< double >::type lon2(lon2SEXP); Rcpp::traits::input_parameter< double >::type lat2(lat2SEXP); Rcpp::traits::input_parameter< double >::type plon(plonSEXP); Rcpp::traits::input_parameter< double >::type plat(platSEXP); Rcpp::traits::input_parameter< bool >::type sign(signSEXP); rcpp_result_gen = Rcpp::wrap(dist2track(lon1, lat1, lon2, lat2, plon, plat, sign)); return rcpp_result_gen; END_RCPP } // alongTrackDistance double alongTrackDistance(double lon1, double lat1, double lon2, double lat2, double plon, double plat); RcppExport SEXP _terra_alongTrackDistance(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP plonSEXP, SEXP platSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< double >::type lon1(lon1SEXP); Rcpp::traits::input_parameter< double >::type lat1(lat1SEXP); Rcpp::traits::input_parameter< double >::type lon2(lon2SEXP); Rcpp::traits::input_parameter< double >::type lat2(lat2SEXP); Rcpp::traits::input_parameter< double >::type plon(plonSEXP); Rcpp::traits::input_parameter< double >::type plat(platSEXP); rcpp_result_gen = Rcpp::wrap(alongTrackDistance(lon1, lat1, lon2, lat2, plon, plat)); return rcpp_result_gen; END_RCPP } // dist2segment double dist2segment(double plon, double plat, double lon1, double lat1, double lon2, double lat2); RcppExport SEXP _terra_dist2segment(SEXP plonSEXP, SEXP platSEXP, SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< double >::type plon(plonSEXP); Rcpp::traits::input_parameter< double >::type plat(platSEXP); Rcpp::traits::input_parameter< double >::type lon1(lon1SEXP); Rcpp::traits::input_parameter< double >::type lat1(lat1SEXP); Rcpp::traits::input_parameter< double >::type lon2(lon2SEXP); Rcpp::traits::input_parameter< double >::type lat2(lat2SEXP); rcpp_result_gen = Rcpp::wrap(dist2segment(plon, plat, lon1, lat1, lon2, lat2)); return rcpp_result_gen; END_RCPP } // dist2segmentPoint double dist2segmentPoint(double plon, double plat, double lon1, double lat1, double lon2, double lat2, double& ilon, double& ilat); RcppExport SEXP _terra_dist2segmentPoint(SEXP plonSEXP, SEXP platSEXP, SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP ilonSEXP, SEXP ilatSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< double >::type plon(plonSEXP); Rcpp::traits::input_parameter< double >::type plat(platSEXP); Rcpp::traits::input_parameter< double >::type lon1(lon1SEXP); Rcpp::traits::input_parameter< double >::type lat1(lat1SEXP); Rcpp::traits::input_parameter< double >::type lon2(lon2SEXP); Rcpp::traits::input_parameter< double >::type lat2(lat2SEXP); Rcpp::traits::input_parameter< double& >::type ilon(ilonSEXP); Rcpp::traits::input_parameter< double& >::type ilat(ilatSEXP); rcpp_result_gen = Rcpp::wrap(dist2segmentPoint(plon, plat, lon1, lat1, lon2, lat2, ilon, ilat)); return rcpp_result_gen; END_RCPP } // intermediate std::vector> intermediate(double lon1, double lat1, double lon2, double lat2, int n, double distance); RcppExport SEXP _terra_intermediate(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP nSEXP, SEXP distanceSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< double >::type lon1(lon1SEXP); Rcpp::traits::input_parameter< double >::type lat1(lat1SEXP); Rcpp::traits::input_parameter< double >::type lon2(lon2SEXP); Rcpp::traits::input_parameter< double >::type lat2(lat2SEXP); Rcpp::traits::input_parameter< int >::type n(nSEXP); Rcpp::traits::input_parameter< double >::type distance(distanceSEXP); rcpp_result_gen = Rcpp::wrap(intermediate(lon1, lat1, lon2, lat2, n, distance)); return rcpp_result_gen; END_RCPP } RcppExport SEXP _rcpp_module_boot_spat(); static const R_CallMethodDef CallEntries[] = { {"_terra_proj_version", (DL_FUNC) &_terra_proj_version, 0}, {"_terra_hex2rgb", (DL_FUNC) &_terra_hex2rgb, 1}, {"_terra_rgb2hex", (DL_FUNC) &_terra_rgb2hex, 1}, {"_terra_sameSRS", (DL_FUNC) &_terra_sameSRS, 2}, {"_terra_getCRSname", (DL_FUNC) &_terra_getCRSname, 1}, {"_terra_getLinearUnits", (DL_FUNC) &_terra_getLinearUnits, 1}, {"_terra_geotransform", (DL_FUNC) &_terra_geotransform, 1}, {"_terra_ginfo", (DL_FUNC) &_terra_ginfo, 3}, {"_terra_sd_info", (DL_FUNC) &_terra_sd_info, 1}, {"_terra_gdal_version", (DL_FUNC) &_terra_gdal_version, 0}, {"_terra_geos_version", (DL_FUNC) &_terra_geos_version, 2}, {"_terra_metatdata", (DL_FUNC) &_terra_metatdata, 1}, {"_terra_sdsmetatdata", (DL_FUNC) &_terra_sdsmetatdata, 1}, {"_terra_sdsmetatdataparsed", (DL_FUNC) &_terra_sdsmetatdataparsed, 1}, {"_terra_gdal_drivers", (DL_FUNC) &_terra_gdal_drivers, 0}, {"_terra_set_gdal_warnings", (DL_FUNC) &_terra_set_gdal_warnings, 1}, {"_terra_gdal_init", (DL_FUNC) &_terra_gdal_init, 1}, {"_terra_percRank", (DL_FUNC) &_terra_percRank, 5}, {"_terra_setGDALCacheSizeMB", (DL_FUNC) &_terra_setGDALCacheSizeMB, 1}, {"_terra_getGDALCacheSizeMB", (DL_FUNC) &_terra_getGDALCacheSizeMB, 0}, {"_terra_get_proj_search_paths", (DL_FUNC) &_terra_get_proj_search_paths, 0}, {"_terra_set_proj_search_paths", (DL_FUNC) &_terra_set_proj_search_paths, 1}, {"_terra_PROJ_network", (DL_FUNC) &_terra_PROJ_network, 2}, {"_terra_dist_lonlat", (DL_FUNC) &_terra_dist_lonlat, 4}, {"_terra_dir_lonlat", (DL_FUNC) &_terra_dir_lonlat, 4}, {"_terra_dist2track", (DL_FUNC) &_terra_dist2track, 7}, {"_terra_alongTrackDistance", (DL_FUNC) &_terra_alongTrackDistance, 6}, {"_terra_dist2segment", (DL_FUNC) &_terra_dist2segment, 6}, {"_terra_dist2segmentPoint", (DL_FUNC) &_terra_dist2segmentPoint, 8}, {"_terra_intermediate", (DL_FUNC) &_terra_intermediate, 6}, {"_rcpp_module_boot_spat", (DL_FUNC) &_rcpp_module_boot_spat, 0}, {NULL, NULL, 0} }; RcppExport void R_init_terra(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); } terra/src/RcppFunctions.cpp0000644000175000017500000003041514201035750015611 0ustar nileshnilesh#include #include "spatRasterMultiple.h" #include "string_utils.h" #include "gdal_priv.h" #include "gdalio.h" #include "ogr_spatialref.h" #define GEOS_USE_ONLY_R_API #include #if GDAL_VERSION_MAJOR >= 3 #include "proj.h" #define projh #if PROJ_VERSION_MAJOR > 7 # define PROJ_71 #else # if PROJ_VERSION_MAJOR == 7 # if PROJ_VERSION_MINOR >= 1 # define PROJ_71 # endif # endif #endif #else #include #endif //from sf #ifdef projh // [[Rcpp::export]] std::string proj_version() { std::stringstream buffer; buffer << PROJ_VERSION_MAJOR << "." << PROJ_VERSION_MINOR << "." << PROJ_VERSION_PATCH; return buffer.str(); } #else std::string proj_version() { int v = PJ_VERSION; std::stringstream buffer; buffer << v / 100 << "." << (v / 10) % 10 << "." << v % 10; return buffer.str(); } #endif // [[Rcpp::export]] std::vector hex2rgb(std::string s) { unsigned char r, g, b; s = s.erase(0,1); // remove the "#" sscanf(s.c_str(), "%02hhx%02hhx%02hhx", &r, &g, &b); std::vector x = {r, g, b}; return x; } // [[Rcpp::export]] std::string rgb2hex(std::vector x) { std::stringstream ss; ss << "#" << std::hex << std::setw(6) << (x[0] << 16 | x[1] << 8 | x[2] ); std::string s = ss.str(); //std::transform(s.begin(), s.end(), s.begin(), ::toupper); str_replace_all(s, " ", "0"); return s; } // [[Rcpp::export(name = ".sameSRS")]] bool sameSRS(std::string x, std::string y) { std::string msg; SpatSRS srs; if (!srs.set(x, msg)) return false; return srs.is_same(y, false); } // [[Rcpp::export(name = ".SRSinfo")]] std::vector getCRSname(std::string s) { OGRSpatialReference x; OGRErr erro = x.SetFromUserInput(s.c_str()); if (erro != OGRERR_NONE) { return {"unknown", "", "", "", ""}; } std::string node; if (x.IsGeographic()) { node = "geogcs"; } else { node = "projcs"; } const char *value; std::string name = ""; value = x.GetAttrValue(node.c_str()); if (value != NULL) { name = value; } std::string aname = ""; value = x.GetAuthorityName(node.c_str()); if (value != NULL) { aname = value; } std::string acode = ""; value = x.GetAuthorityCode(node.c_str()); if (value != NULL) { acode = value; } double west, south, east, north; west = -10000; east = -10000; south = -10000; north = -10000; std::string aoi="", box=""; #if GDAL_VERSION_MAJOR >= 3 if (x.GetAreaOfUse(&west, &south, &east, &north, &value)) { if (value != NULL) { if (west > -1000) { aoi = value; box = std::to_string(west) + ", " + std::to_string(east) + ", " + std::to_string(north) + ", " + std::to_string(south); } } } #endif return {name, aname, acode, aoi, box}; } // [[Rcpp::export(name = ".getLinearUnits")]] double getLinearUnits(std::string s) { std::string msg; SpatSRS srs; if (!srs.set(s, msg)) return NAN; return srs.to_meter(); } // [[Rcpp::export(name = ".geotransform")]] std::vector geotransform(std::string fname) { std::vector out; GDALDataset *poDataset = static_cast(GDALOpenEx( fname.c_str(), GDAL_OF_RASTER | GDAL_OF_READONLY, NULL, NULL, NULL )); if( poDataset == NULL ) { Rcpp::Rcout << "cannot read from: " + fname << std::endl; return out; } double gt[6]; if( poDataset->GetGeoTransform( gt ) != CE_None ) { Rcpp::Rcout << "bad geotransform" << std::endl; } out = std::vector(std::begin(gt), std::end(gt)); GDALClose( (GDALDatasetH) poDataset ); return out; } // [[Rcpp::export(name = ".gdalinfo")]] std::string ginfo(std::string filename, std::vector options, std::vector oo) { std::string out = gdalinfo(filename, options, oo); return out; } // [[Rcpp::export(name = ".sdinfo")]] std::vector> sd_info(std::string filename) { std::vector> sd = sdinfo(filename); return sd; } // [[Rcpp::export(name = ".gdal_version")]] std::string gdal_version() { const char* what = "RELEASE_NAME"; const char* x = GDALVersionInfo(what); std::string s = (std::string) x; return s; } // [[Rcpp::export(name = ".geos_version")]] std::string geos_version(bool runtime = false, bool capi = false) { if (runtime) return GEOSversion(); else { if (capi) return GEOS_CAPI_VERSION; else return GEOS_VERSION; } } // [[Rcpp::export(name = ".metadata")]] std::vector metatdata(std::string filename) { std::vector m = get_metadata(filename); return m; } // [[Rcpp::export(name = ".sdsmetadata")]] std::vector sdsmetatdata(std::string filename) { std::vector m = get_metadata_sds(filename); return m; } // [[Rcpp::export(name = ".parsedsdsmetadata")]] std::vector> sdsmetatdataparsed(std::string filename) { std::vector m = sdsmetatdata(filename); std::vector> s = parse_metadata_sds(m); return s; } /* // [[Rcpp::export(name = ".gdaldrivers")]] std::vector> gdal_drivers() { size_t n = GetGDALDriverManager()->GetDriverCount(); std::vector> s(5); for (size_t i=0; iGetDriver(i); s[0].push_back(poDriver->GetDescription()); s[4].push_back(poDriver->GetMetadataItem( GDAL_DMD_LONGNAME ) ); papszMetadata = poDriver->GetMetadata(); bool rst = CSLFetchBoolean( papszMetadata, GDAL_DCAP_RASTER, FALSE); s[1].push_back(std::to_string(rst)); bool create = CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE); bool copy = CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE); s[2].push_back(std::to_string(create + copy)); bool vsi = CSLFetchBoolean( papszMetadata, GDAL_DCAP_VIRTUALIO, FALSE); s[3].push_back(std::to_string(vsi)); } return s; } */ // [[Rcpp::export(name = ".gdaldrivers")]] std::vector> gdal_drivers() { size_t n = GetGDALDriverManager()->GetDriverCount(); std::vector> s(5, std::vector(n)); GDALDriver *poDriver; char **papszMetadata; for (size_t i=0; iGetDriver(i); const char* ss = poDriver->GetDescription(); if (ss != NULL ) s[0][i] = ss; ss = poDriver->GetMetadataItem( GDAL_DMD_LONGNAME ); if (ss != NULL ) s[4][i] = ss; papszMetadata = poDriver->GetMetadata(); bool rst = CSLFetchBoolean( papszMetadata, GDAL_DCAP_RASTER, FALSE); s[1][i] = std::to_string(rst); bool create = CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE); bool copy = CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE); s[2][i] = std::to_string(create + copy); bool vsi = CSLFetchBoolean( papszMetadata, GDAL_DCAP_VIRTUALIO, FALSE); s[3][i] = std::to_string(vsi); } return s; } template inline void warningNoCall(const char* fmt, Args&&... args ) { Rf_warningcall(R_NilValue, tfm::format(fmt, std::forward(args)... ).c_str()); } template inline void NORET stopNoCall(const char* fmt, Args&&... args) { throw Rcpp::exception(tfm::format(fmt, std::forward(args)... ).c_str(), false); } static void __err_warning(CPLErr eErrClass, int err_no, const char *msg) { switch ( eErrClass ) { case 0: break; case 1: case 2: warningNoCall("%s (GDAL %d)", msg, err_no); break; case 3: warningNoCall("%s (GDAL error %d)", msg, err_no); break; case 4: stopNoCall("%s (GDAL unrecoverable error %d)", msg, err_no); break; default: warningNoCall("%s (GDAL error class %d, #%d)", msg, eErrClass, err_no); break; } return; } static void __err_error(CPLErr eErrClass, int err_no, const char *msg) { switch ( eErrClass ) { case 0: case 1: case 2: break; case 3: warningNoCall("%s (GDAL error %d)", msg, err_no); break; case 4: stopNoCall("%s (GDAL unrecoverable error %d)", msg, err_no); break; default: stopNoCall("%s (GDAL unrecoverable error %d)", msg, err_no); break; } return; } static void __err_fatal(CPLErr eErrClass, int err_no, const char *msg) { switch ( eErrClass ) { case 0: case 1: case 2: case 3: break; case 4: stopNoCall("%s (GDAL unrecoverable error %d)", msg, err_no); break; default: break; } return; } static void __err_none(CPLErr eErrClass, int err_no, const char *msg) { return; } // [[Rcpp::export(name = ".set_gdal_warnings")]] void set_gdal_warnings(int level) { if (level==4) { CPLSetErrorHandler((CPLErrorHandler)__err_none); } else if (level==1) { CPLSetErrorHandler((CPLErrorHandler)__err_warning); } else if (level==2) { CPLSetErrorHandler((CPLErrorHandler)__err_error); } else { CPLSetErrorHandler((CPLErrorHandler)__err_fatal); } } // [[Rcpp::export(name = ".gdalinit")]] void gdal_init(std::string path) { set_gdal_warnings(2); GDALAllRegister(); OGRRegisterAll(); CPLSetConfigOption("GDAL_MAX_BAND_COUNT", "9999999"); CPLSetConfigOption("OGR_CT_FORCE_TRADITIONAL_GIS_ORDER", "YES"); //GDALregistred = true; #if GDAL_VERSION_MAJOR >= 3 if (path != "") { const char *cp = path.c_str(); proj_context_set_search_paths(PJ_DEFAULT_CTX, 1, &cp); } #endif #ifdef PROJ71 proj_context_set_enable_network(PJ_DEFAULT_CTX, 1); #endif } // [[Rcpp::export(name = ".precRank")]] std::vector percRank(std::vector x, std::vector y, double minc, double maxc, int tail) { std::vector out; out.reserve(y.size()); size_t nx = x.size(); for (size_t i=0; i maxc )) { out.push_back( 0 ); } else { size_t b = 0; size_t t = 0; for (size_t j=0; j x[j]) { b++; } else if (y[i] == x[j]) { t++; } else { // y is sorted, so we need not continue break; } } double z = (b + 0.5 * t) / nx; if (tail == 1) { // both if (z > 0.5) { z = 2 * (1 - z); } else { z = 2 * z; } } else if (tail == 2) { // high if (z < 0.5) { z = 1; } else { z = 2 * (1 - z); } } else { // if (tail == 3) { // low if (z > 0.5) { z = 1; } else { z = 2 * z; } } out.push_back(z); } } return(out); } // [[Rcpp::export(name = ".setGDALCacheSizeMB")]] void setGDALCacheSizeMB(double x) { GDALSetCacheMax64(static_cast(x) * 1024 * 1024); } // [[Rcpp::export(name = ".getGDALCacheSizeMB")]] double getGDALCacheSizeMB() { return static_cast(GDALGetCacheMax64() / 1024 / 1024); } // convert NULL-terminated array of strings to std::vector std::vector charpp2vect(char **cp) { std::vector out; if (cp == NULL) return out; size_t i=0; while (cp[i] != NULL) { out.push_back(cp[i]); i++; } return out; } // [[Rcpp::export(name = ".get_proj_search_paths")]] std::vector get_proj_search_paths() { std::vector out; #if GDAL_VERSION_NUM >= 3000300 char **cp = OSRGetPROJSearchPaths(); out = charpp2vect(cp); CSLDestroy(cp); #else out.push_back("error: GDAL >= 3.0.3 required"); #endif return out; } // [[Rcpp::export(name = ".set_proj_search_paths")]] bool set_proj_search_paths(std::vector paths) { if (!paths.size()) { return false; } #if GDAL_VERSION_NUM >= 3000000 std::vector cpaths(paths.size()+1); for (size_t i = 0; i < paths.size(); i++) { cpaths[i] = (char *) (paths[i].c_str()); } cpaths[cpaths.size()] = NULL; OSRSetPROJSearchPaths(cpaths.data()); return true; #else return false; #endif } // [[Rcpp::export(name = ".PROJ_network")]] std::string PROJ_network(bool enable, std::string url) { std::string s = ""; #ifdef PROJ_71 if (enable) { proj_context_set_enable_network(PJ_DEFAULT_CTX, 1); if (url.size() > 5) { proj_context_set_url_endpoint(PJ_DEFAULT_CTX, url.c_str()); } s = proj_context_get_url_endpoint(PJ_DEFAULT_CTX); } else { // disable: proj_context_set_enable_network(PJ_DEFAULT_CTX, 0); } #endif return s; } terra/src/geodesic.h0000644000175000017500000013031114201035750014237 0ustar nileshnilesh/** * \file geodesic.h * \brief API for the geodesic routines in C * * This an implementation in C of the geodesic algorithms described in * - C. F. F. Karney, * * Algorithms for geodesics, * J. Geodesy 87, 43--55 (2013); * DOI: * 10.1007/s00190-012-0578-z; * addenda: * geod-addenda.html. * . * The principal advantages of these algorithms over previous ones (e.g., * Vincenty, 1975) are * - accurate to round off for |f| < 1/50; * - the solution of the inverse problem is always found; * - differential and integral properties of geodesics are computed. * * The shortest path between two points on the ellipsoid at (\e lat1, \e * lon1) and (\e lat2, \e lon2) is called the geodesic. Its length is * \e s12 and the geodesic from point 1 to point 2 has forward azimuths * \e azi1 and \e azi2 at the two end points. * * Traditionally two geodesic problems are considered: * - the direct problem -- given \e lat1, \e lon1, \e s12, and \e azi1, * determine \e lat2, \e lon2, and \e azi2. This is solved by the function * geod_direct(). * - the inverse problem -- given \e lat1, \e lon1, and \e lat2, \e lon2, * determine \e s12, \e azi1, and \e azi2. This is solved by the function * geod_inverse(). * * The ellipsoid is specified by its equatorial radius \e a (typically in * meters) and flattening \e f. The routines are accurate to round off with * double precision arithmetic provided that |f| < 1/50; for the * WGS84 ellipsoid, the errors are less than 15 nanometers. (Reasonably * accurate results are obtained for |f| < 1/5.) For a prolate * ellipsoid, specify \e f < 0. * * The routines also calculate several other quantities of interest * - \e S12 is the area between the geodesic from point 1 to point 2 and the * equator; i.e., it is the area, measured counter-clockwise, of the * quadrilateral with corners (\e lat1,\e lon1), (0,\e lon1), (0,\e lon2), * and (\e lat2,\e lon2). * - \e m12, the reduced length of the geodesic is defined such that if * the initial azimuth is perturbed by \e dazi1 (radians) then the * second point is displaced by \e m12 \e dazi1 in the direction * perpendicular to the geodesic. On a curved surface the reduced * length obeys a symmetry relation, \e m12 + \e m21 = 0. On a flat * surface, we have \e m12 = \e s12. * - \e M12 and \e M21 are geodesic scales. If two geodesics are * parallel at point 1 and separated by a small distance \e dt, then * they are separated by a distance \e M12 \e dt at point 2. \e M21 * is defined similarly (with the geodesics being parallel to one * another at point 2). On a flat surface, we have \e M12 = \e M21 * = 1. * - \e a12 is the arc length on the auxiliary sphere. This is a * construct for converting the problem to one in spherical * trigonometry. \e a12 is measured in degrees. The spherical arc * length from one equator crossing to the next is always 180°. * * If points 1, 2, and 3 lie on a single geodesic, then the following * addition rules hold: * - \e s13 = \e s12 + \e s23 * - \e a13 = \e a12 + \e a23 * - \e S13 = \e S12 + \e S23 * - \e m13 = \e m12 \e M23 + \e m23 \e M21 * - \e M13 = \e M12 \e M23 − (1 − \e M12 \e M21) \e * m23 / \e m12 * - \e M31 = \e M32 \e M21 − (1 − \e M23 \e M32) \e * m12 / \e m23 * * The shortest distance returned by the solution of the inverse problem is * (obviously) uniquely defined. However, in a few special cases there are * multiple azimuths which yield the same shortest distance. Here is a * catalog of those cases: * - \e lat1 = −\e lat2 (with neither point at a pole). If \e azi1 = \e * azi2, the geodesic is unique. Otherwise there are two geodesics and the * second one is obtained by setting [\e azi1, \e azi2] → [\e azi2, \e * azi1], [\e M12, \e M21] → [\e M21, \e M12], \e S12 → −\e * S12. (This occurs when the longitude difference is near ±180° * for oblate ellipsoids.) * - \e lon2 = \e lon1 ± 180° (with neither point at a pole). If \e * azi1 = 0° or ±180°, the geodesic is unique. Otherwise * there are two geodesics and the second one is obtained by setting [\e * azi1, \e azi2] → [−\e azi1, −\e azi2], \e S12 → * −\e S12. (This occurs when \e lat2 is near −\e lat1 for * prolate ellipsoids.) * - Points 1 and 2 at opposite poles. There are infinitely many geodesics * which can be generated by setting [\e azi1, \e azi2] → [\e azi1, \e * azi2] + [\e d, −\e d], for arbitrary \e d. (For spheres, this * prescription applies when points 1 and 2 are antipodal.) * - \e s12 = 0 (coincident points). There are infinitely many geodesics which * can be generated by setting [\e azi1, \e azi2] → [\e azi1, \e azi2] + * [\e d, \e d], for arbitrary \e d. * * These routines are a simple transcription of the corresponding C++ classes * in GeographicLib. The * "class data" is represented by the structs geod_geodesic, geod_geodesicline, * geod_polygon and pointers to these objects are passed as initial arguments * to the member functions. Most of the internal comments have been retained. * However, in the process of transcription some documentation has been lost * and the documentation for the C++ classes, GeographicLib::Geodesic, * GeographicLib::GeodesicLine, and GeographicLib::PolygonAreaT, should be * consulted. The C++ code remains the "reference implementation". Think * twice about restructuring the internals of the C code since this may make * porting fixes from the C++ code more difficult. * * Copyright (c) Charles Karney (2012-2021) and licensed * under the MIT/X11 License. For more information, see * https://geographiclib.sourceforge.io/ * * This library was distributed with * GeographicLib 1.52. **********************************************************************/ #if !defined(GEODESIC_H) #define GEODESIC_H 1 /** * The major version of the geodesic library. (This tracks the version of * GeographicLib.) **********************************************************************/ #define GEODESIC_VERSION_MAJOR 1 /** * The minor version of the geodesic library. (This tracks the version of * GeographicLib.) **********************************************************************/ #define GEODESIC_VERSION_MINOR 52 /** * The patch level of the geodesic library. (This tracks the version of * GeographicLib.) **********************************************************************/ #define GEODESIC_VERSION_PATCH 0 /** * Pack the version components into a single integer. Users should not rely on * this particular packing of the components of the version number; see the * documentation for GEODESIC_VERSION, below. **********************************************************************/ #define GEODESIC_VERSION_NUM(a,b,c) ((((a) * 10000 + (b)) * 100) + (c)) /** * The version of the geodesic library as a single integer, packed as MMmmmmpp * where MM is the major version, mmmm is the minor version, and pp is the * patch level. Users should not rely on this particular packing of the * components of the version number. Instead they should use a test such as * @code{.c} #if GEODESIC_VERSION >= GEODESIC_VERSION_NUM(1,40,0) ... #endif * @endcode **********************************************************************/ #define GEODESIC_VERSION \ GEODESIC_VERSION_NUM(GEODESIC_VERSION_MAJOR, \ GEODESIC_VERSION_MINOR, \ GEODESIC_VERSION_PATCH) #if !defined(GEOD_DLL) #if defined(_MSC_VER) && defined(PROJ_MSVC_DLL_EXPORT) #define GEOD_DLL __declspec(dllexport) #elif defined(__GNUC__) #define GEOD_DLL __attribute__ ((visibility("default"))) #else #define GEOD_DLL #endif #endif #if defined(PROJ_RENAME_SYMBOLS) #include "proj_symbol_rename.h" #endif #if defined(__cplusplus) extern "C" { #endif /** * The struct containing information about the ellipsoid. This must be * initialized by geod_init() before use. **********************************************************************/ struct geod_geodesic { double a; /**< the equatorial radius */ double f; /**< the flattening */ /**< @cond SKIP */ double f1, e2, ep2, n, b, c2, etol2; double A3x[6], C3x[15], C4x[21]; /**< @endcond */ }; /** * The struct containing information about a single geodesic. This must be * initialized by geod_lineinit(), geod_directline(), geod_gendirectline(), * or geod_inverseline() before use. **********************************************************************/ struct geod_geodesicline { double lat1; /**< the starting latitude */ double lon1; /**< the starting longitude */ double azi1; /**< the starting azimuth */ double a; /**< the equatorial radius */ double f; /**< the flattening */ double salp1; /**< sine of \e azi1 */ double calp1; /**< cosine of \e azi1 */ double a13; /**< arc length to reference point */ double s13; /**< distance to reference point */ /**< @cond SKIP */ double b, c2, f1, salp0, calp0, k2, ssig1, csig1, dn1, stau1, ctau1, somg1, comg1, A1m1, A2m1, A3c, B11, B21, B31, A4, B41; double C1a[6+1], C1pa[6+1], C2a[6+1], C3a[6], C4a[6]; /**< @endcond */ unsigned caps; /**< the capabilities */ }; /** * The struct for accumulating information about a geodesic polygon. This is * used for computing the perimeter and area of a polygon. This must be * initialized by geod_polygon_init() before use. **********************************************************************/ struct geod_polygon { double lat; /**< the current latitude */ double lon; /**< the current longitude */ /**< @cond SKIP */ double lat0; double lon0; double A[2]; double P[2]; int polyline; int crossings; /**< @endcond */ unsigned num; /**< the number of points so far */ }; /** * Initialize a geod_geodesic object. * * @param[out] g a pointer to the object to be initialized. * @param[in] a the equatorial radius (meters). * @param[in] f the flattening. **********************************************************************/ void GEOD_DLL geod_init(struct geod_geodesic* g, double a, double f); /** * Solve the direct geodesic problem. * * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in] lat1 latitude of point 1 (degrees). * @param[in] lon1 longitude of point 1 (degrees). * @param[in] azi1 azimuth at point 1 (degrees). * @param[in] s12 distance from point 1 to point 2 (meters); it can be * negative. * @param[out] plat2 pointer to the latitude of point 2 (degrees). * @param[out] plon2 pointer to the longitude of point 2 (degrees). * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees). * * \e g must have been initialized with a call to geod_init(). \e lat1 * should be in the range [−90°, 90°]. The values of \e lon2 * and \e azi2 returned are in the range [−180°, 180°]. Any of * the "return" arguments \e plat2, etc., may be replaced by 0, if you do not * need some quantities computed. * * If either point is at a pole, the azimuth is defined by keeping the * longitude fixed, writing \e lat = ±(90° − ε), and * taking the limit ε → 0+. An arc length greater that 180° * signifies a geodesic which is not a shortest path. (For a prolate * ellipsoid, an additional condition is necessary for a shortest path: the * longitudinal extent must not exceed of 180°.) * * Example, determine the point 10000 km NE of JFK: @code{.c} struct geod_geodesic g; double lat, lon; geod_init(&g, 6378137, 1/298.257223563); geod_direct(&g, 40.64, -73.78, 45.0, 10e6, &lat, &lon, 0); printf("%.5f %.5f\n", lat, lon); @endcode **********************************************************************/ void GEOD_DLL geod_direct(const struct geod_geodesic* g, double lat1, double lon1, double azi1, double s12, double* plat2, double* plon2, double* pazi2); /** * The general direct geodesic problem. * * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in] lat1 latitude of point 1 (degrees). * @param[in] lon1 longitude of point 1 (degrees). * @param[in] azi1 azimuth at point 1 (degrees). * @param[in] flags bitor'ed combination of geod_flags(); \e flags & * GEOD_ARCMODE determines the meaning of \e s12_a12 and \e flags & * GEOD_LONG_UNROLL "unrolls" \e lon2. * @param[in] s12_a12 if \e flags & GEOD_ARCMODE is 0, this is the distance * from point 1 to point 2 (meters); otherwise it is the arc length * from point 1 to point 2 (degrees); it can be negative. * @param[out] plat2 pointer to the latitude of point 2 (degrees). * @param[out] plon2 pointer to the longitude of point 2 (degrees). * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees). * @param[out] ps12 pointer to the distance from point 1 to point 2 * (meters). * @param[out] pm12 pointer to the reduced length of geodesic (meters). * @param[out] pM12 pointer to the geodesic scale of point 2 relative to * point 1 (dimensionless). * @param[out] pM21 pointer to the geodesic scale of point 1 relative to * point 2 (dimensionless). * @param[out] pS12 pointer to the area under the geodesic * (meters2). * @return \e a12 arc length from point 1 to point 2 (degrees). * * \e g must have been initialized with a call to geod_init(). \e lat1 * should be in the range [−90°, 90°]. The function value \e * a12 equals \e s12_a12 if \e flags & GEOD_ARCMODE. Any of the "return" * arguments, \e plat2, etc., may be replaced by 0, if you do not need some * quantities computed. * * With \e flags & GEOD_LONG_UNROLL bit set, the longitude is "unrolled" so * that the quantity \e lon2 − \e lon1 indicates how many times and in * what sense the geodesic encircles the ellipsoid. **********************************************************************/ double GEOD_DLL geod_gendirect(const struct geod_geodesic* g, double lat1, double lon1, double azi1, unsigned flags, double s12_a12, double* plat2, double* plon2, double* pazi2, double* ps12, double* pm12, double* pM12, double* pM21, double* pS12); /** * Solve the inverse geodesic problem. * * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in] lat1 latitude of point 1 (degrees). * @param[in] lon1 longitude of point 1 (degrees). * @param[in] lat2 latitude of point 2 (degrees). * @param[in] lon2 longitude of point 2 (degrees). * @param[out] ps12 pointer to the distance from point 1 to point 2 * (meters). * @param[out] pazi1 pointer to the azimuth at point 1 (degrees). * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees). * * \e g must have been initialized with a call to geod_init(). \e lat1 and * \e lat2 should be in the range [−90°, 90°]. The values of * \e azi1 and \e azi2 returned are in the range [−180°, 180°]. * Any of the "return" arguments, \e ps12, etc., may be replaced by 0, if you * do not need some quantities computed. * * If either point is at a pole, the azimuth is defined by keeping the * longitude fixed, writing \e lat = ±(90° − ε), and * taking the limit ε → 0+. * * The solution to the inverse problem is found using Newton's method. If * this fails to converge (this is very unlikely in geodetic applications * but does occur for very eccentric ellipsoids), then the bisection method * is used to refine the solution. * * Example, determine the distance between JFK and Singapore Changi Airport: @code{.c} struct geod_geodesic g; double s12; geod_init(&g, 6378137, 1/298.257223563); geod_inverse(&g, 40.64, -73.78, 1.36, 103.99, &s12, 0, 0); printf("%.3f\n", s12); @endcode **********************************************************************/ void GEOD_DLL geod_inverse(const struct geod_geodesic* g, double lat1, double lon1, double lat2, double lon2, double* ps12, double* pazi1, double* pazi2); /** * The general inverse geodesic calculation. * * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in] lat1 latitude of point 1 (degrees). * @param[in] lon1 longitude of point 1 (degrees). * @param[in] lat2 latitude of point 2 (degrees). * @param[in] lon2 longitude of point 2 (degrees). * @param[out] ps12 pointer to the distance from point 1 to point 2 * (meters). * @param[out] pazi1 pointer to the azimuth at point 1 (degrees). * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees). * @param[out] pm12 pointer to the reduced length of geodesic (meters). * @param[out] pM12 pointer to the geodesic scale of point 2 relative to * point 1 (dimensionless). * @param[out] pM21 pointer to the geodesic scale of point 1 relative to * point 2 (dimensionless). * @param[out] pS12 pointer to the area under the geodesic * (meters2). * @return \e a12 arc length from point 1 to point 2 (degrees). * * \e g must have been initialized with a call to geod_init(). \e lat1 and * \e lat2 should be in the range [−90°, 90°]. Any of the * "return" arguments \e ps12, etc., may be replaced by 0, if you do not need * some quantities computed. **********************************************************************/ double GEOD_DLL geod_geninverse(const struct geod_geodesic* g, double lat1, double lon1, double lat2, double lon2, double* ps12, double* pazi1, double* pazi2, double* pm12, double* pM12, double* pM21, double* pS12); /** * Initialize a geod_geodesicline object. * * @param[out] l a pointer to the object to be initialized. * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in] lat1 latitude of point 1 (degrees). * @param[in] lon1 longitude of point 1 (degrees). * @param[in] azi1 azimuth at point 1 (degrees). * @param[in] caps bitor'ed combination of geod_mask() values specifying the * capabilities the geod_geodesicline object should possess, i.e., which * quantities can be returned in calls to geod_position() and * geod_genposition(). * * \e g must have been initialized with a call to geod_init(). \e lat1 * should be in the range [−90°, 90°]. * * The geod_mask values are [see geod_mask()]: * - \e caps |= GEOD_LATITUDE for the latitude \e lat2; this is * added automatically, * - \e caps |= GEOD_LONGITUDE for the latitude \e lon2, * - \e caps |= GEOD_AZIMUTH for the latitude \e azi2; this is * added automatically, * - \e caps |= GEOD_DISTANCE for the distance \e s12, * - \e caps |= GEOD_REDUCEDLENGTH for the reduced length \e m12, * - \e caps |= GEOD_GEODESICSCALE for the geodesic scales \e M12 * and \e M21, * - \e caps |= GEOD_AREA for the area \e S12, * - \e caps |= GEOD_DISTANCE_IN permits the length of the * geodesic to be given in terms of \e s12; without this capability the * length can only be specified in terms of arc length. * . * A value of \e caps = 0 is treated as GEOD_LATITUDE | GEOD_LONGITUDE | * GEOD_AZIMUTH | GEOD_DISTANCE_IN (to support the solution of the "standard" * direct problem). * * When initialized by this function, point 3 is undefined (l->s13 = l->a13 = * NaN). **********************************************************************/ void GEOD_DLL geod_lineinit(struct geod_geodesicline* l, const struct geod_geodesic* g, double lat1, double lon1, double azi1, unsigned caps); /** * Initialize a geod_geodesicline object in terms of the direct geodesic * problem. * * @param[out] l a pointer to the object to be initialized. * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in] lat1 latitude of point 1 (degrees). * @param[in] lon1 longitude of point 1 (degrees). * @param[in] azi1 azimuth at point 1 (degrees). * @param[in] s12 distance from point 1 to point 2 (meters); it can be * negative. * @param[in] caps bitor'ed combination of geod_mask() values specifying the * capabilities the geod_geodesicline object should possess, i.e., which * quantities can be returned in calls to geod_position() and * geod_genposition(). * * This function sets point 3 of the geod_geodesicline to correspond to point * 2 of the direct geodesic problem. See geod_lineinit() for more * information. **********************************************************************/ void GEOD_DLL geod_directline(struct geod_geodesicline* l, const struct geod_geodesic* g, double lat1, double lon1, double azi1, double s12, unsigned caps); /** * Initialize a geod_geodesicline object in terms of the direct geodesic * problem specified in terms of either distance or arc length. * * @param[out] l a pointer to the object to be initialized. * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in] lat1 latitude of point 1 (degrees). * @param[in] lon1 longitude of point 1 (degrees). * @param[in] azi1 azimuth at point 1 (degrees). * @param[in] flags either GEOD_NOFLAGS or GEOD_ARCMODE to determining the * meaning of the \e s12_a12. * @param[in] s12_a12 if \e flags = GEOD_NOFLAGS, this is the distance * from point 1 to point 2 (meters); if \e flags = GEOD_ARCMODE, it is * the arc length from point 1 to point 2 (degrees); it can be * negative. * @param[in] caps bitor'ed combination of geod_mask() values specifying the * capabilities the geod_geodesicline object should possess, i.e., which * quantities can be returned in calls to geod_position() and * geod_genposition(). * * This function sets point 3 of the geod_geodesicline to correspond to point * 2 of the direct geodesic problem. See geod_lineinit() for more * information. **********************************************************************/ void GEOD_DLL geod_gendirectline(struct geod_geodesicline* l, const struct geod_geodesic* g, double lat1, double lon1, double azi1, unsigned flags, double s12_a12, unsigned caps); /** * Initialize a geod_geodesicline object in terms of the inverse geodesic * problem. * * @param[out] l a pointer to the object to be initialized. * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in] lat1 latitude of point 1 (degrees). * @param[in] lon1 longitude of point 1 (degrees). * @param[in] lat2 latitude of point 2 (degrees). * @param[in] lon2 longitude of point 2 (degrees). * @param[in] caps bitor'ed combination of geod_mask() values specifying the * capabilities the geod_geodesicline object should possess, i.e., which * quantities can be returned in calls to geod_position() and * geod_genposition(). * * This function sets point 3 of the geod_geodesicline to correspond to point * 2 of the inverse geodesic problem. See geod_lineinit() for more * information. **********************************************************************/ void GEOD_DLL geod_inverseline(struct geod_geodesicline* l, const struct geod_geodesic* g, double lat1, double lon1, double lat2, double lon2, unsigned caps); /** * Compute the position along a geod_geodesicline. * * @param[in] l a pointer to the geod_geodesicline object specifying the * geodesic line. * @param[in] s12 distance from point 1 to point 2 (meters); it can be * negative. * @param[out] plat2 pointer to the latitude of point 2 (degrees). * @param[out] plon2 pointer to the longitude of point 2 (degrees); requires * that \e l was initialized with \e caps |= GEOD_LONGITUDE. * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees). * * \e l must have been initialized with a call, e.g., to geod_lineinit(), * with \e caps |= GEOD_DISTANCE_IN (or \e caps = 0). The values of \e lon2 * and \e azi2 returned are in the range [−180°, 180°]. Any of * the "return" arguments \e plat2, etc., may be replaced by 0, if you do not * need some quantities computed. * * Example, compute way points between JFK and Singapore Changi Airport * the "obvious" way using geod_direct(): @code{.c} struct geod_geodesic g; double s12, azi1, lat[101],lon[101]; int i; geod_init(&g, 6378137, 1/298.257223563); geod_inverse(&g, 40.64, -73.78, 1.36, 103.99, &s12, &azi1, 0); for (i = 0; i < 101; ++i) { geod_direct(&g, 40.64, -73.78, azi1, i * s12 * 0.01, lat + i, lon + i, 0); printf("%.5f %.5f\n", lat[i], lon[i]); } @endcode * A faster way using geod_position(): @code{.c} struct geod_geodesic g; struct geod_geodesicline l; double lat[101],lon[101]; int i; geod_init(&g, 6378137, 1/298.257223563); geod_inverseline(&l, &g, 40.64, -73.78, 1.36, 103.99, 0); for (i = 0; i <= 100; ++i) { geod_position(&l, i * l.s13 * 0.01, lat + i, lon + i, 0); printf("%.5f %.5f\n", lat[i], lon[i]); } @endcode **********************************************************************/ void GEOD_DLL geod_position(const struct geod_geodesicline* l, double s12, double* plat2, double* plon2, double* pazi2); /** * The general position function. * * @param[in] l a pointer to the geod_geodesicline object specifying the * geodesic line. * @param[in] flags bitor'ed combination of geod_flags(); \e flags & * GEOD_ARCMODE determines the meaning of \e s12_a12 and \e flags & * GEOD_LONG_UNROLL "unrolls" \e lon2; if \e flags & GEOD_ARCMODE is 0, * then \e l must have been initialized with \e caps |= GEOD_DISTANCE_IN. * @param[in] s12_a12 if \e flags & GEOD_ARCMODE is 0, this is the * distance from point 1 to point 2 (meters); otherwise it is the * arc length from point 1 to point 2 (degrees); it can be * negative. * @param[out] plat2 pointer to the latitude of point 2 (degrees). * @param[out] plon2 pointer to the longitude of point 2 (degrees); requires * that \e l was initialized with \e caps |= GEOD_LONGITUDE. * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees). * @param[out] ps12 pointer to the distance from point 1 to point 2 * (meters); requires that \e l was initialized with \e caps |= * GEOD_DISTANCE. * @param[out] pm12 pointer to the reduced length of geodesic (meters); * requires that \e l was initialized with \e caps |= GEOD_REDUCEDLENGTH. * @param[out] pM12 pointer to the geodesic scale of point 2 relative to * point 1 (dimensionless); requires that \e l was initialized with \e caps * |= GEOD_GEODESICSCALE. * @param[out] pM21 pointer to the geodesic scale of point 1 relative to * point 2 (dimensionless); requires that \e l was initialized with \e caps * |= GEOD_GEODESICSCALE. * @param[out] pS12 pointer to the area under the geodesic * (meters2); requires that \e l was initialized with \e caps |= * GEOD_AREA. * @return \e a12 arc length from point 1 to point 2 (degrees). * * \e l must have been initialized with a call to geod_lineinit() with \e * caps |= GEOD_DISTANCE_IN. The value \e azi2 returned is in the range * [−180°, 180°]. Any of the "return" arguments \e plat2, * etc., may be replaced by 0, if you do not need some quantities * computed. Requesting a value which \e l is not capable of computing * is not an error; the corresponding argument will not be altered. * * With \e flags & GEOD_LONG_UNROLL bit set, the longitude is "unrolled" so * that the quantity \e lon2 − \e lon1 indicates how many times and in * what sense the geodesic encircles the ellipsoid. * * Example, compute way points between JFK and Singapore Changi Airport using * geod_genposition(). In this example, the points are evenly space in arc * length (and so only approximately equally spaced in distance). This is * faster than using geod_position() and would be appropriate if drawing the * path on a map. @code{.c} struct geod_geodesic g; struct geod_geodesicline l; double lat[101], lon[101]; int i; geod_init(&g, 6378137, 1/298.257223563); geod_inverseline(&l, &g, 40.64, -73.78, 1.36, 103.99, GEOD_LATITUDE | GEOD_LONGITUDE); for (i = 0; i <= 100; ++i) { geod_genposition(&l, GEOD_ARCMODE, i * l.a13 * 0.01, lat + i, lon + i, 0, 0, 0, 0, 0, 0); printf("%.5f %.5f\n", lat[i], lon[i]); } @endcode **********************************************************************/ double GEOD_DLL geod_genposition(const struct geod_geodesicline* l, unsigned flags, double s12_a12, double* plat2, double* plon2, double* pazi2, double* ps12, double* pm12, double* pM12, double* pM21, double* pS12); /** * Specify position of point 3 in terms of distance. * * @param[in,out] l a pointer to the geod_geodesicline object. * @param[in] s13 the distance from point 1 to point 3 (meters); it * can be negative. * * This is only useful if the geod_geodesicline object has been constructed * with \e caps |= GEOD_DISTANCE_IN. **********************************************************************/ void GEOD_DLL geod_setdistance(struct geod_geodesicline* l, double s13); /** * Specify position of point 3 in terms of either distance or arc length. * * @param[in,out] l a pointer to the geod_geodesicline object. * @param[in] flags either GEOD_NOFLAGS or GEOD_ARCMODE to determining the * meaning of the \e s13_a13. * @param[in] s13_a13 if \e flags = GEOD_NOFLAGS, this is the distance * from point 1 to point 3 (meters); if \e flags = GEOD_ARCMODE, it is * the arc length from point 1 to point 3 (degrees); it can be * negative. * * If flags = GEOD_NOFLAGS, this calls geod_setdistance(). If flags = * GEOD_ARCMODE, the \e s13 is only set if the geod_geodesicline object has * been constructed with \e caps |= GEOD_DISTANCE. **********************************************************************/ void GEOD_DLL geod_gensetdistance(struct geod_geodesicline* l, unsigned flags, double s13_a13); /** * Initialize a geod_polygon object. * * @param[out] p a pointer to the object to be initialized. * @param[in] polylinep non-zero if a polyline instead of a polygon. * * If \e polylinep is zero, then the sequence of vertices and edges added by * geod_polygon_addpoint() and geod_polygon_addedge() define a polygon and * the perimeter and area are returned by geod_polygon_compute(). If \e * polylinep is non-zero, then the vertices and edges define a polyline and * only the perimeter is returned by geod_polygon_compute(). * * The area and perimeter are accumulated at two times the standard floating * point precision to guard against the loss of accuracy with many-sided * polygons. At any point you can ask for the perimeter and area so far. * * An example of the use of this function is given in the documentation for * geod_polygon_compute(). **********************************************************************/ void GEOD_DLL geod_polygon_init(struct geod_polygon* p, int polylinep); /** * Clear the polygon, allowing a new polygon to be started. * * @param[in,out] p a pointer to the object to be cleared. **********************************************************************/ void GEOD_DLL geod_polygon_clear(struct geod_polygon* p); /** * Add a point to the polygon or polyline. * * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in,out] p a pointer to the geod_polygon object specifying the * polygon. * @param[in] lat the latitude of the point (degrees). * @param[in] lon the longitude of the point (degrees). * * \e g and \e p must have been initialized with calls to geod_init() and * geod_polygon_init(), respectively. The same \e g must be used for all the * points and edges in a polygon. \e lat should be in the range * [−90°, 90°]. * * An example of the use of this function is given in the documentation for * geod_polygon_compute(). **********************************************************************/ void GEOD_DLL geod_polygon_addpoint(const struct geod_geodesic* g, struct geod_polygon* p, double lat, double lon); /** * Add an edge to the polygon or polyline. * * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in,out] p a pointer to the geod_polygon object specifying the * polygon. * @param[in] azi azimuth at current point (degrees). * @param[in] s distance from current point to next point (meters). * * \e g and \e p must have been initialized with calls to geod_init() and * geod_polygon_init(), respectively. The same \e g must be used for all the * points and edges in a polygon. This does nothing if no points have been * added yet. The \e lat and \e lon fields of \e p give the location of the * new vertex. **********************************************************************/ void GEOD_DLL geod_polygon_addedge(const struct geod_geodesic* g, struct geod_polygon* p, double azi, double s); /** * Return the results for a polygon. * * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in] p a pointer to the geod_polygon object specifying the polygon. * @param[in] reverse if non-zero then clockwise (instead of * counter-clockwise) traversal counts as a positive area. * @param[in] sign if non-zero then return a signed result for the area if * the polygon is traversed in the "wrong" direction instead of returning * the area for the rest of the earth. * @param[out] pA pointer to the area of the polygon (meters2); * only set if \e polyline is non-zero in the call to geod_polygon_init(). * @param[out] pP pointer to the perimeter of the polygon or length of the * polyline (meters). * @return the number of points. * * The area and perimeter are accumulated at two times the standard floating * point precision to guard against the loss of accuracy with many-sided * polygons. Arbitrarily complex polygons are allowed. In the case of * self-intersecting polygons the area is accumulated "algebraically", e.g., * the areas of the 2 loops in a figure-8 polygon will partially cancel. * There's no need to "close" the polygon by repeating the first vertex. Set * \e pA or \e pP to zero, if you do not want the corresponding quantity * returned. * * More points can be added to the polygon after this call. * * Example, compute the perimeter and area of the geodesic triangle with * vertices (0°N,0°E), (0°N,90°E), (90°N,0°E). @code{.c} double A, P; int n; struct geod_geodesic g; struct geod_polygon p; geod_init(&g, 6378137, 1/298.257223563); geod_polygon_init(&p, 0); geod_polygon_addpoint(&g, &p, 0, 0); geod_polygon_addpoint(&g, &p, 0, 90); geod_polygon_addpoint(&g, &p, 90, 0); n = geod_polygon_compute(&g, &p, 0, 1, &A, &P); printf("%d %.8f %.3f\n", n, P, A); @endcode **********************************************************************/ unsigned GEOD_DLL geod_polygon_compute(const struct geod_geodesic* g, const struct geod_polygon* p, int reverse, int sign, double* pA, double* pP); /** * Return the results assuming a tentative final test point is added; * however, the data for the test point is not saved. This lets you report a * running result for the perimeter and area as the user moves the mouse * cursor. Ordinary floating point arithmetic is used to accumulate the data * for the test point; thus the area and perimeter returned are less accurate * than if geod_polygon_addpoint() and geod_polygon_compute() are used. * * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in] p a pointer to the geod_polygon object specifying the polygon. * @param[in] lat the latitude of the test point (degrees). * @param[in] lon the longitude of the test point (degrees). * @param[in] reverse if non-zero then clockwise (instead of * counter-clockwise) traversal counts as a positive area. * @param[in] sign if non-zero then return a signed result for the area if * the polygon is traversed in the "wrong" direction instead of returning * the area for the rest of the earth. * @param[out] pA pointer to the area of the polygon (meters2); * only set if \e polyline is non-zero in the call to geod_polygon_init(). * @param[out] pP pointer to the perimeter of the polygon or length of the * polyline (meters). * @return the number of points. * * \e lat should be in the range [−90°, 90°]. **********************************************************************/ unsigned GEOD_DLL geod_polygon_testpoint(const struct geod_geodesic* g, const struct geod_polygon* p, double lat, double lon, int reverse, int sign, double* pA, double* pP); /** * Return the results assuming a tentative final test point is added via an * azimuth and distance; however, the data for the test point is not saved. * This lets you report a running result for the perimeter and area as the * user moves the mouse cursor. Ordinary floating point arithmetic is used * to accumulate the data for the test point; thus the area and perimeter * returned are less accurate than if geod_polygon_addedge() and * geod_polygon_compute() are used. * * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in] p a pointer to the geod_polygon object specifying the polygon. * @param[in] azi azimuth at current point (degrees). * @param[in] s distance from current point to final test point (meters). * @param[in] reverse if non-zero then clockwise (instead of * counter-clockwise) traversal counts as a positive area. * @param[in] sign if non-zero then return a signed result for the area if * the polygon is traversed in the "wrong" direction instead of returning * the area for the rest of the earth. * @param[out] pA pointer to the area of the polygon (meters2); * only set if \e polyline is non-zero in the call to geod_polygon_init(). * @param[out] pP pointer to the perimeter of the polygon or length of the * polyline (meters). * @return the number of points. **********************************************************************/ unsigned GEOD_DLL geod_polygon_testedge(const struct geod_geodesic* g, const struct geod_polygon* p, double azi, double s, int reverse, int sign, double* pA, double* pP); /** * A simple interface for computing the area of a geodesic polygon. * * @param[in] g a pointer to the geod_geodesic object specifying the * ellipsoid. * @param[in] lats an array of latitudes of the polygon vertices (degrees). * @param[in] lons an array of longitudes of the polygon vertices (degrees). * @param[in] n the number of vertices. * @param[out] pA pointer to the area of the polygon (meters2). * @param[out] pP pointer to the perimeter of the polygon (meters). * * \e lats should be in the range [−90°, 90°]. * * Arbitrarily complex polygons are allowed. In the case self-intersecting * of polygons the area is accumulated "algebraically", e.g., the areas of * the 2 loops in a figure-8 polygon will partially cancel. There's no need * to "close" the polygon by repeating the first vertex. The area returned * is signed with counter-clockwise traversal being treated as positive. * * Example, compute the area of Antarctica: @code{.c} double lats[] = {-72.9, -71.9, -74.9, -74.3, -77.5, -77.4, -71.7, -65.9, -65.7, -66.6, -66.9, -69.8, -70.0, -71.0, -77.3, -77.9, -74.7}, lons[] = {-74, -102, -102, -131, -163, 163, 172, 140, 113, 88, 59, 25, -4, -14, -33, -46, -61}; struct geod_geodesic g; double A, P; geod_init(&g, 6378137, 1/298.257223563); geod_polygonarea(&g, lats, lons, (sizeof lats) / (sizeof lats[0]), &A, &P); printf("%.0f %.2f\n", A, P); @endcode **********************************************************************/ void GEOD_DLL geod_polygonarea(const struct geod_geodesic* g, double lats[], double lons[], int n, double* pA, double* pP); /** * mask values for the \e caps argument to geod_lineinit(). **********************************************************************/ enum geod_mask { GEOD_NONE = 0U, /**< Calculate nothing */ GEOD_LATITUDE = 1U<<7 | 0U, /**< Calculate latitude */ GEOD_LONGITUDE = 1U<<8 | 1U<<3, /**< Calculate longitude */ GEOD_AZIMUTH = 1U<<9 | 0U, /**< Calculate azimuth */ GEOD_DISTANCE = 1U<<10 | 1U<<0, /**< Calculate distance */ GEOD_DISTANCE_IN = 1U<<11 | 1U<<0 | 1U<<1,/**< Allow distance as input */ GEOD_REDUCEDLENGTH= 1U<<12 | 1U<<0 | 1U<<2,/**< Calculate reduced length */ GEOD_GEODESICSCALE= 1U<<13 | 1U<<0 | 1U<<2,/**< Calculate geodesic scale */ GEOD_AREA = 1U<<14 | 1U<<4, /**< Calculate reduced length */ GEOD_ALL = 0x7F80U| 0x1FU /**< Calculate everything */ }; /** * flag values for the \e flags argument to geod_gendirect() and * geod_genposition() **********************************************************************/ enum geod_flags { GEOD_NOFLAGS = 0U, /**< No flags */ GEOD_ARCMODE = 1U<<0, /**< Position given in terms of arc distance */ GEOD_LONG_UNROLL = 1U<<15 /**< Unroll the longitude */ }; #if defined(__cplusplus) } #endif #endif terra/src/geodesic.c0000644000175000017500000021313314201035750014236 0ustar nileshnilesh/** * \file geodesic.c * \brief Implementation of the geodesic routines in C * * For the full documentation see geodesic.h. **********************************************************************/ /** @cond SKIP */ /* * This is a C implementation of the geodesic algorithms described in * * C. F. F. Karney, * Algorithms for geodesics, * J. Geodesy 87, 43--55 (2013); * https://doi.org/10.1007/s00190-012-0578-z * Addenda: https://geographiclib.sourceforge.io/geod-addenda.html * * See the comments in geodesic.h for documentation. * * Copyright (c) Charles Karney (2012-2021) and licensed * under the MIT/X11 License. For more information, see * https://geographiclib.sourceforge.io/ */ #include "geodesic.h" #include #include #include #if !defined(__cplusplus) #define nullptr 0 #endif #define GEOGRAPHICLIB_GEODESIC_ORDER 6 #define nA1 GEOGRAPHICLIB_GEODESIC_ORDER #define nC1 GEOGRAPHICLIB_GEODESIC_ORDER #define nC1p GEOGRAPHICLIB_GEODESIC_ORDER #define nA2 GEOGRAPHICLIB_GEODESIC_ORDER #define nC2 GEOGRAPHICLIB_GEODESIC_ORDER #define nA3 GEOGRAPHICLIB_GEODESIC_ORDER #define nA3x nA3 #define nC3 GEOGRAPHICLIB_GEODESIC_ORDER #define nC3x ((nC3 * (nC3 - 1)) / 2) #define nC4 GEOGRAPHICLIB_GEODESIC_ORDER #define nC4x ((nC4 * (nC4 + 1)) / 2) #define nC (GEOGRAPHICLIB_GEODESIC_ORDER + 1) typedef double real; typedef int boolx; static unsigned init = 0; static const int FALSE = 0; static const int TRUE = 1; static unsigned digits, maxit1, maxit2; static real epsilon, realmin, pi, degree, NaN, tiny, tol0, tol1, tol2, tolb, xthresh; static void Init(void) { if (!init) { digits = DBL_MANT_DIG; epsilon = DBL_EPSILON; realmin = DBL_MIN; #if defined(M_PI) pi = M_PI; #else pi = atan2(0.0, -1.0); #endif maxit1 = 20; maxit2 = maxit1 + digits + 10; tiny = sqrt(realmin); tol0 = epsilon; /* Increase multiplier in defn of tol1 from 100 to 200 to fix inverse case * 52.784459512564 0 -52.784459512563990912 179.634407464943777557 * which otherwise failed for Visual Studio 10 (Release and Debug) */ tol1 = 200 * tol0; tol2 = sqrt(tol0); /* Check on bisection interval */ tolb = tol0 * tol2; xthresh = 1000 * tol2; degree = pi/180; NaN = nan("0"); init = 1; } } enum captype { CAP_NONE = 0U, CAP_C1 = 1U<<0, CAP_C1p = 1U<<1, CAP_C2 = 1U<<2, CAP_C3 = 1U<<3, CAP_C4 = 1U<<4, CAP_ALL = 0x1FU, OUT_ALL = 0x7F80U }; static real sq(real x) { return x * x; } static real sumx(real u, real v, real* t) { volatile real s = u + v; volatile real up = s - v; volatile real vpp = s - up; up -= u; vpp -= v; if (t) *t = -(up + vpp); /* error-free sum: * u + v = s + t * = round(u + v) + t */ return s; } static real polyval(int N, const real p[], real x) { real y = N < 0 ? 0 : *p++; while (--N >= 0) y = y * x + *p++; return y; } /* mimic C++ std::min and std::max */ static real minx(real a, real b) { return (b < a) ? b : a; } static real maxx(real a, real b) { return (a < b) ? b : a; } static void swapx(real* x, real* y) { real t = *x; *x = *y; *y = t; } static void norm2(real* sinx, real* cosx) { #if defined(_MSC_VER) && defined(_M_IX86) /* hypot for Visual Studio (A=win32) fails monotonicity, e.g., with * x = 0.6102683302836215 * y1 = 0.7906090004346522 * y2 = y1 + 1e-16 * the test * hypot(x, y2) >= hypot(x, y1) * fails. See also * https://bugs.python.org/issue43088 */ real r = sqrt(*sinx * *sinx + *cosx * *cosx); #else real r = hypot(*sinx, *cosx); #endif *sinx /= r; *cosx /= r; } static real AngNormalize(real x) { x = remainder(x, (real)(360)); return x != -180 ? x : 180; } static real LatFix(real x) { return fabs(x) > 90 ? NaN : x; } static real AngDiff(real x, real y, real* e) { real t, d = AngNormalize(sumx(AngNormalize(-x), AngNormalize(y), &t)); /* Here y - x = d + t (mod 360), exactly, where d is in (-180,180] and * abs(t) <= eps (eps = 2^-45 for doubles). The only case where the * addition of t takes the result outside the range (-180,180] is d = 180 * and t > 0. The case, d = -180 + eps, t = -eps, can't happen, since * sum would have returned the exact result in such a case (i.e., given t * = 0). */ return sumx(d == 180 && t > 0 ? -180 : d, t, e); } static real AngRound(real x) { const real z = 1/(real)(16); volatile real y; if (x == 0) return 0; y = fabs(x); /* The compiler mustn't "simplify" z - (z - y) to y */ y = y < z ? z - (z - y) : y; return x < 0 ? -y : y; } static void sincosdx(real x, real* sinx, real* cosx) { /* In order to minimize round-off errors, this function exactly reduces * the argument to the range [-45, 45] before converting it to radians. */ real r, s, c; int q = 0; r = remquo(x, (real)(90), &q); /* now abs(r) <= 45 */ r *= degree; /* Possibly could call the gnu extension sincos */ s = sin(r); c = cos(r); switch ((unsigned)q & 3U) { case 0U: *sinx = s; *cosx = c; break; case 1U: *sinx = c; *cosx = -s; break; case 2U: *sinx = -s; *cosx = -c; break; default: *sinx = -c; *cosx = s; break; /* case 3U */ } if (x != 0) { *sinx += (real)(0); *cosx += (real)(0); } } static real atan2dx(real y, real x) { /* In order to minimize round-off errors, this function rearranges the * arguments so that result of atan2 is in the range [-pi/4, pi/4] before * converting it to degrees and mapping the result to the correct * quadrant. */ int q = 0; real ang; if (fabs(y) > fabs(x)) { swapx(&x, &y); q = 2; } if (x < 0) { x = -x; ++q; } /* here x >= 0 and x >= abs(y), so angle is in [-pi/4, pi/4] */ ang = atan2(y, x) / degree; switch (q) { /* Note that atan2d(-0.0, 1.0) will return -0. However, we expect that * atan2d will not be called with y = -0. If need be, include * * case 0: ang = 0 + ang; break; */ case 1: ang = (y >= 0 ? 180 : -180) - ang; break; case 2: ang = 90 - ang; break; case 3: ang = -90 + ang; break; default: break; } return ang; } static void A3coeff(struct geod_geodesic* g); static void C3coeff(struct geod_geodesic* g); static void C4coeff(struct geod_geodesic* g); static real SinCosSeries(boolx sinp, real sinx, real cosx, const real c[], int n); static void Lengths(const struct geod_geodesic* g, real eps, real sig12, real ssig1, real csig1, real dn1, real ssig2, real csig2, real dn2, real cbet1, real cbet2, real* ps12b, real* pm12b, real* pm0, real* pM12, real* pM21, /* Scratch area of the right size */ real Ca[]); static real Astroid(real x, real y); static real InverseStart(const struct geod_geodesic* g, real sbet1, real cbet1, real dn1, real sbet2, real cbet2, real dn2, real lam12, real slam12, real clam12, real* psalp1, real* pcalp1, /* Only updated if return val >= 0 */ real* psalp2, real* pcalp2, /* Only updated for short lines */ real* pdnm, /* Scratch area of the right size */ real Ca[]); static real Lambda12(const struct geod_geodesic* g, real sbet1, real cbet1, real dn1, real sbet2, real cbet2, real dn2, real salp1, real calp1, real slam120, real clam120, real* psalp2, real* pcalp2, real* psig12, real* pssig1, real* pcsig1, real* pssig2, real* pcsig2, real* peps, real* pdomg12, boolx diffp, real* pdlam12, /* Scratch area of the right size */ real Ca[]); static real A3f(const struct geod_geodesic* g, real eps); static void C3f(const struct geod_geodesic* g, real eps, real c[]); static void C4f(const struct geod_geodesic* g, real eps, real c[]); static real A1m1f(real eps); static void C1f(real eps, real c[]); static void C1pf(real eps, real c[]); static real A2m1f(real eps); static void C2f(real eps, real c[]); static int transit(real lon1, real lon2); static int transitdirect(real lon1, real lon2); static void accini(real s[]); static void acccopy(const real s[], real t[]); static void accadd(real s[], real y); static real accsum(const real s[], real y); static void accneg(real s[]); static void accrem(real s[], real y); static real areareduceA(real area[], real area0, int crossings, boolx reverse, boolx sign); static real areareduceB(real area, real area0, int crossings, boolx reverse, boolx sign); void geod_init(struct geod_geodesic* g, real a, real f) { if (!init) Init(); g->a = a; g->f = f; g->f1 = 1 - g->f; g->e2 = g->f * (2 - g->f); g->ep2 = g->e2 / sq(g->f1); /* e2 / (1 - e2) */ g->n = g->f / ( 2 - g->f); g->b = g->a * g->f1; g->c2 = (sq(g->a) + sq(g->b) * (g->e2 == 0 ? 1 : (g->e2 > 0 ? atanh(sqrt(g->e2)) : atan(sqrt(-g->e2))) / sqrt(fabs(g->e2))))/2; /* authalic radius squared */ /* The sig12 threshold for "really short". Using the auxiliary sphere * solution with dnm computed at (bet1 + bet2) / 2, the relative error in the * azimuth consistency check is sig12^2 * abs(f) * min(1, 1-f/2) / 2. (Error * measured for 1/100 < b/a < 100 and abs(f) >= 1/1000. For a given f and * sig12, the max error occurs for lines near the pole. If the old rule for * computing dnm = (dn1 + dn2)/2 is used, then the error increases by a * factor of 2.) Setting this equal to epsilon gives sig12 = etol2. Here * 0.1 is a safety factor (error decreased by 100) and max(0.001, abs(f)) * stops etol2 getting too large in the nearly spherical case. */ g->etol2 = 0.1 * tol2 / sqrt( maxx((real)(0.001), fabs(g->f)) * minx((real)(1), 1 - g->f/2) / 2 ); A3coeff(g); C3coeff(g); C4coeff(g); } static void geod_lineinit_int(struct geod_geodesicline* l, const struct geod_geodesic* g, real lat1, real lon1, real azi1, real salp1, real calp1, unsigned caps) { real cbet1, sbet1, eps; l->a = g->a; l->f = g->f; l->b = g->b; l->c2 = g->c2; l->f1 = g->f1; /* If caps is 0 assume the standard direct calculation */ l->caps = (caps ? caps : GEOD_DISTANCE_IN | GEOD_LONGITUDE) | /* always allow latitude and azimuth and unrolling of longitude */ GEOD_LATITUDE | GEOD_AZIMUTH | GEOD_LONG_UNROLL; l->lat1 = LatFix(lat1); l->lon1 = lon1; l->azi1 = azi1; l->salp1 = salp1; l->calp1 = calp1; sincosdx(AngRound(l->lat1), &sbet1, &cbet1); sbet1 *= l->f1; /* Ensure cbet1 = +epsilon at poles */ norm2(&sbet1, &cbet1); cbet1 = maxx(tiny, cbet1); l->dn1 = sqrt(1 + g->ep2 * sq(sbet1)); /* Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0), */ l->salp0 = l->salp1 * cbet1; /* alp0 in [0, pi/2 - |bet1|] */ /* Alt: calp0 = hypot(sbet1, calp1 * cbet1). The following * is slightly better (consider the case salp1 = 0). */ l->calp0 = hypot(l->calp1, l->salp1 * sbet1); /* Evaluate sig with tan(bet1) = tan(sig1) * cos(alp1). * sig = 0 is nearest northward crossing of equator. * With bet1 = 0, alp1 = pi/2, we have sig1 = 0 (equatorial line). * With bet1 = pi/2, alp1 = -pi, sig1 = pi/2 * With bet1 = -pi/2, alp1 = 0 , sig1 = -pi/2 * Evaluate omg1 with tan(omg1) = sin(alp0) * tan(sig1). * With alp0 in (0, pi/2], quadrants for sig and omg coincide. * No atan2(0,0) ambiguity at poles since cbet1 = +epsilon. * With alp0 = 0, omg1 = 0 for alp1 = 0, omg1 = pi for alp1 = pi. */ l->ssig1 = sbet1; l->somg1 = l->salp0 * sbet1; l->csig1 = l->comg1 = sbet1 != 0 || l->calp1 != 0 ? cbet1 * l->calp1 : 1; norm2(&l->ssig1, &l->csig1); /* sig1 in (-pi, pi] */ /* norm2(somg1, comg1); -- don't need to normalize! */ l->k2 = sq(l->calp0) * g->ep2; eps = l->k2 / (2 * (1 + sqrt(1 + l->k2)) + l->k2); if (l->caps & CAP_C1) { real s, c; l->A1m1 = A1m1f(eps); C1f(eps, l->C1a); l->B11 = SinCosSeries(TRUE, l->ssig1, l->csig1, l->C1a, nC1); s = sin(l->B11); c = cos(l->B11); /* tau1 = sig1 + B11 */ l->stau1 = l->ssig1 * c + l->csig1 * s; l->ctau1 = l->csig1 * c - l->ssig1 * s; /* Not necessary because C1pa reverts C1a * B11 = -SinCosSeries(TRUE, stau1, ctau1, C1pa, nC1p); */ } if (l->caps & CAP_C1p) C1pf(eps, l->C1pa); if (l->caps & CAP_C2) { l->A2m1 = A2m1f(eps); C2f(eps, l->C2a); l->B21 = SinCosSeries(TRUE, l->ssig1, l->csig1, l->C2a, nC2); } if (l->caps & CAP_C3) { C3f(g, eps, l->C3a); l->A3c = -l->f * l->salp0 * A3f(g, eps); l->B31 = SinCosSeries(TRUE, l->ssig1, l->csig1, l->C3a, nC3-1); } if (l->caps & CAP_C4) { C4f(g, eps, l->C4a); /* Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0) */ l->A4 = sq(l->a) * l->calp0 * l->salp0 * g->e2; l->B41 = SinCosSeries(FALSE, l->ssig1, l->csig1, l->C4a, nC4); } l->a13 = l->s13 = NaN; } void geod_lineinit(struct geod_geodesicline* l, const struct geod_geodesic* g, real lat1, real lon1, real azi1, unsigned caps) { real salp1, calp1; azi1 = AngNormalize(azi1); /* Guard against underflow in salp0 */ sincosdx(AngRound(azi1), &salp1, &calp1); geod_lineinit_int(l, g, lat1, lon1, azi1, salp1, calp1, caps); } void geod_gendirectline(struct geod_geodesicline* l, const struct geod_geodesic* g, real lat1, real lon1, real azi1, unsigned flags, real s12_a12, unsigned caps) { geod_lineinit(l, g, lat1, lon1, azi1, caps); geod_gensetdistance(l, flags, s12_a12); } void geod_directline(struct geod_geodesicline* l, const struct geod_geodesic* g, real lat1, real lon1, real azi1, real s12, unsigned caps) { geod_gendirectline(l, g, lat1, lon1, azi1, GEOD_NOFLAGS, s12, caps); } real geod_genposition(const struct geod_geodesicline* l, unsigned flags, real s12_a12, real* plat2, real* plon2, real* pazi2, real* ps12, real* pm12, real* pM12, real* pM21, real* pS12) { real lat2 = 0, lon2 = 0, azi2 = 0, s12 = 0, m12 = 0, M12 = 0, M21 = 0, S12 = 0; /* Avoid warning about uninitialized B12. */ real sig12, ssig12, csig12, B12 = 0, AB1 = 0; real omg12, lam12, lon12; real ssig2, csig2, sbet2, cbet2, somg2, comg2, salp2, calp2, dn2; unsigned outmask = (plat2 ? GEOD_LATITUDE : GEOD_NONE) | (plon2 ? GEOD_LONGITUDE : GEOD_NONE) | (pazi2 ? GEOD_AZIMUTH : GEOD_NONE) | (ps12 ? GEOD_DISTANCE : GEOD_NONE) | (pm12 ? GEOD_REDUCEDLENGTH : GEOD_NONE) | (pM12 || pM21 ? GEOD_GEODESICSCALE : GEOD_NONE) | (pS12 ? GEOD_AREA : GEOD_NONE); outmask &= l->caps & OUT_ALL; if (!( (flags & GEOD_ARCMODE || (l->caps & (GEOD_DISTANCE_IN & OUT_ALL))) )) /* Impossible distance calculation requested */ return NaN; if (flags & GEOD_ARCMODE) { /* Interpret s12_a12 as spherical arc length */ sig12 = s12_a12 * degree; sincosdx(s12_a12, &ssig12, &csig12); } else { /* Interpret s12_a12 as distance */ real tau12 = s12_a12 / (l->b * (1 + l->A1m1)), s = sin(tau12), c = cos(tau12); /* tau2 = tau1 + tau12 */ B12 = - SinCosSeries(TRUE, l->stau1 * c + l->ctau1 * s, l->ctau1 * c - l->stau1 * s, l->C1pa, nC1p); sig12 = tau12 - (B12 - l->B11); ssig12 = sin(sig12); csig12 = cos(sig12); if (fabs(l->f) > 0.01) { /* Reverted distance series is inaccurate for |f| > 1/100, so correct * sig12 with 1 Newton iteration. The following table shows the * approximate maximum error for a = WGS_a() and various f relative to * GeodesicExact. * erri = the error in the inverse solution (nm) * errd = the error in the direct solution (series only) (nm) * errda = the error in the direct solution (series + 1 Newton) (nm) * * f erri errd errda * -1/5 12e6 1.2e9 69e6 * -1/10 123e3 12e6 765e3 * -1/20 1110 108e3 7155 * -1/50 18.63 200.9 27.12 * -1/100 18.63 23.78 23.37 * -1/150 18.63 21.05 20.26 * 1/150 22.35 24.73 25.83 * 1/100 22.35 25.03 25.31 * 1/50 29.80 231.9 30.44 * 1/20 5376 146e3 10e3 * 1/10 829e3 22e6 1.5e6 * 1/5 157e6 3.8e9 280e6 */ real serr; ssig2 = l->ssig1 * csig12 + l->csig1 * ssig12; csig2 = l->csig1 * csig12 - l->ssig1 * ssig12; B12 = SinCosSeries(TRUE, ssig2, csig2, l->C1a, nC1); serr = (1 + l->A1m1) * (sig12 + (B12 - l->B11)) - s12_a12 / l->b; sig12 = sig12 - serr / sqrt(1 + l->k2 * sq(ssig2)); ssig12 = sin(sig12); csig12 = cos(sig12); /* Update B12 below */ } } /* sig2 = sig1 + sig12 */ ssig2 = l->ssig1 * csig12 + l->csig1 * ssig12; csig2 = l->csig1 * csig12 - l->ssig1 * ssig12; dn2 = sqrt(1 + l->k2 * sq(ssig2)); if (outmask & (GEOD_DISTANCE | GEOD_REDUCEDLENGTH | GEOD_GEODESICSCALE)) { if (flags & GEOD_ARCMODE || fabs(l->f) > 0.01) B12 = SinCosSeries(TRUE, ssig2, csig2, l->C1a, nC1); AB1 = (1 + l->A1m1) * (B12 - l->B11); } /* sin(bet2) = cos(alp0) * sin(sig2) */ sbet2 = l->calp0 * ssig2; /* Alt: cbet2 = hypot(csig2, salp0 * ssig2); */ cbet2 = hypot(l->salp0, l->calp0 * csig2); if (cbet2 == 0) /* I.e., salp0 = 0, csig2 = 0. Break the degeneracy in this case */ cbet2 = csig2 = tiny; /* tan(alp0) = cos(sig2)*tan(alp2) */ salp2 = l->salp0; calp2 = l->calp0 * csig2; /* No need to normalize */ if (outmask & GEOD_DISTANCE) s12 = (flags & GEOD_ARCMODE) ? l->b * ((1 + l->A1m1) * sig12 + AB1) : s12_a12; if (outmask & GEOD_LONGITUDE) { real E = copysign(1, l->salp0); /* east or west going? */ /* tan(omg2) = sin(alp0) * tan(sig2) */ somg2 = l->salp0 * ssig2; comg2 = csig2; /* No need to normalize */ /* omg12 = omg2 - omg1 */ omg12 = (flags & GEOD_LONG_UNROLL) ? E * (sig12 - (atan2( ssig2, csig2) - atan2( l->ssig1, l->csig1)) + (atan2(E * somg2, comg2) - atan2(E * l->somg1, l->comg1))) : atan2(somg2 * l->comg1 - comg2 * l->somg1, comg2 * l->comg1 + somg2 * l->somg1); lam12 = omg12 + l->A3c * ( sig12 + (SinCosSeries(TRUE, ssig2, csig2, l->C3a, nC3-1) - l->B31)); lon12 = lam12 / degree; lon2 = (flags & GEOD_LONG_UNROLL) ? l->lon1 + lon12 : AngNormalize(AngNormalize(l->lon1) + AngNormalize(lon12)); } if (outmask & GEOD_LATITUDE) lat2 = atan2dx(sbet2, l->f1 * cbet2); if (outmask & GEOD_AZIMUTH) azi2 = atan2dx(salp2, calp2); if (outmask & (GEOD_REDUCEDLENGTH | GEOD_GEODESICSCALE)) { real B22 = SinCosSeries(TRUE, ssig2, csig2, l->C2a, nC2), AB2 = (1 + l->A2m1) * (B22 - l->B21), J12 = (l->A1m1 - l->A2m1) * sig12 + (AB1 - AB2); if (outmask & GEOD_REDUCEDLENGTH) /* Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure * accurate cancellation in the case of coincident points. */ m12 = l->b * ((dn2 * (l->csig1 * ssig2) - l->dn1 * (l->ssig1 * csig2)) - l->csig1 * csig2 * J12); if (outmask & GEOD_GEODESICSCALE) { real t = l->k2 * (ssig2 - l->ssig1) * (ssig2 + l->ssig1) / (l->dn1 + dn2); M12 = csig12 + (t * ssig2 - csig2 * J12) * l->ssig1 / l->dn1; M21 = csig12 - (t * l->ssig1 - l->csig1 * J12) * ssig2 / dn2; } } if (outmask & GEOD_AREA) { real B42 = SinCosSeries(FALSE, ssig2, csig2, l->C4a, nC4); real salp12, calp12; if (l->calp0 == 0 || l->salp0 == 0) { /* alp12 = alp2 - alp1, used in atan2 so no need to normalize */ salp12 = salp2 * l->calp1 - calp2 * l->salp1; calp12 = calp2 * l->calp1 + salp2 * l->salp1; } else { /* tan(alp) = tan(alp0) * sec(sig) * tan(alp2-alp1) = (tan(alp2) -tan(alp1)) / (tan(alp2)*tan(alp1)+1) * = calp0 * salp0 * (csig1-csig2) / (salp0^2 + calp0^2 * csig1*csig2) * If csig12 > 0, write * csig1 - csig2 = ssig12 * (csig1 * ssig12 / (1 + csig12) + ssig1) * else * csig1 - csig2 = csig1 * (1 - csig12) + ssig12 * ssig1 * No need to normalize */ salp12 = l->calp0 * l->salp0 * (csig12 <= 0 ? l->csig1 * (1 - csig12) + ssig12 * l->ssig1 : ssig12 * (l->csig1 * ssig12 / (1 + csig12) + l->ssig1)); calp12 = sq(l->salp0) + sq(l->calp0) * l->csig1 * csig2; } S12 = l->c2 * atan2(salp12, calp12) + l->A4 * (B42 - l->B41); } /* In the pattern * * if ((outmask & GEOD_XX) && pYY) * *pYY = YY; * * the second check "&& pYY" is redundant. It's there to make the CLang * static analyzer happy. */ if ((outmask & GEOD_LATITUDE) && plat2) *plat2 = lat2; if ((outmask & GEOD_LONGITUDE) && plon2) *plon2 = lon2; if ((outmask & GEOD_AZIMUTH) && pazi2) *pazi2 = azi2; if ((outmask & GEOD_DISTANCE) && ps12) *ps12 = s12; if ((outmask & GEOD_REDUCEDLENGTH) && pm12) *pm12 = m12; if (outmask & GEOD_GEODESICSCALE) { if (pM12) *pM12 = M12; if (pM21) *pM21 = M21; } if ((outmask & GEOD_AREA) && pS12) *pS12 = S12; return (flags & GEOD_ARCMODE) ? s12_a12 : sig12 / degree; } void geod_setdistance(struct geod_geodesicline* l, real s13) { l->s13 = s13; l->a13 = geod_genposition(l, GEOD_NOFLAGS, l->s13, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); } static void geod_setarc(struct geod_geodesicline* l, real a13) { l->a13 = a13; l->s13 = NaN; geod_genposition(l, GEOD_ARCMODE, l->a13, nullptr, nullptr, nullptr, &l->s13, nullptr, nullptr, nullptr, nullptr); } void geod_gensetdistance(struct geod_geodesicline* l, unsigned flags, real s13_a13) { (flags & GEOD_ARCMODE) ? geod_setarc(l, s13_a13) : geod_setdistance(l, s13_a13); } void geod_position(const struct geod_geodesicline* l, real s12, real* plat2, real* plon2, real* pazi2) { geod_genposition(l, FALSE, s12, plat2, plon2, pazi2, nullptr, nullptr, nullptr, nullptr, nullptr); } real geod_gendirect(const struct geod_geodesic* g, real lat1, real lon1, real azi1, unsigned flags, real s12_a12, real* plat2, real* plon2, real* pazi2, real* ps12, real* pm12, real* pM12, real* pM21, real* pS12) { struct geod_geodesicline l; unsigned outmask = (plat2 ? GEOD_LATITUDE : GEOD_NONE) | (plon2 ? GEOD_LONGITUDE : GEOD_NONE) | (pazi2 ? GEOD_AZIMUTH : GEOD_NONE) | (ps12 ? GEOD_DISTANCE : GEOD_NONE) | (pm12 ? GEOD_REDUCEDLENGTH : GEOD_NONE) | (pM12 || pM21 ? GEOD_GEODESICSCALE : GEOD_NONE) | (pS12 ? GEOD_AREA : GEOD_NONE); geod_lineinit(&l, g, lat1, lon1, azi1, /* Automatically supply GEOD_DISTANCE_IN if necessary */ outmask | ((flags & GEOD_ARCMODE) ? GEOD_NONE : GEOD_DISTANCE_IN)); return geod_genposition(&l, flags, s12_a12, plat2, plon2, pazi2, ps12, pm12, pM12, pM21, pS12); } void geod_direct(const struct geod_geodesic* g, real lat1, real lon1, real azi1, real s12, real* plat2, real* plon2, real* pazi2) { geod_gendirect(g, lat1, lon1, azi1, GEOD_NOFLAGS, s12, plat2, plon2, pazi2, nullptr, nullptr, nullptr, nullptr, nullptr); } static real geod_geninverse_int(const struct geod_geodesic* g, real lat1, real lon1, real lat2, real lon2, real* ps12, real* psalp1, real* pcalp1, real* psalp2, real* pcalp2, real* pm12, real* pM12, real* pM21, real* pS12) { real s12 = 0, m12 = 0, M12 = 0, M21 = 0, S12 = 0; real lon12, lon12s; int latsign, lonsign, swapp; real sbet1, cbet1, sbet2, cbet2, s12x = 0, m12x = 0; real dn1, dn2, lam12, slam12, clam12; real a12 = 0, sig12, calp1 = 0, salp1 = 0, calp2 = 0, salp2 = 0; real Ca[nC]; boolx meridian; /* somg12 > 1 marks that it needs to be calculated */ real omg12 = 0, somg12 = 2, comg12 = 0; unsigned outmask = (ps12 ? GEOD_DISTANCE : GEOD_NONE) | (pm12 ? GEOD_REDUCEDLENGTH : GEOD_NONE) | (pM12 || pM21 ? GEOD_GEODESICSCALE : GEOD_NONE) | (pS12 ? GEOD_AREA : GEOD_NONE); outmask &= OUT_ALL; /* Compute longitude difference (AngDiff does this carefully). Result is * in [-180, 180] but -180 is only for west-going geodesics. 180 is for * east-going and meridional geodesics. */ lon12 = AngDiff(lon1, lon2, &lon12s); /* Make longitude difference positive. */ lonsign = lon12 >= 0 ? 1 : -1; /* If very close to being on the same half-meridian, then make it so. */ lon12 = lonsign * AngRound(lon12); lon12s = AngRound((180 - lon12) - lonsign * lon12s); lam12 = lon12 * degree; if (lon12 > 90) { sincosdx(lon12s, &slam12, &clam12); clam12 = -clam12; } else sincosdx(lon12, &slam12, &clam12); /* If really close to the equator, treat as on equator. */ lat1 = AngRound(LatFix(lat1)); lat2 = AngRound(LatFix(lat2)); /* Swap points so that point with higher (abs) latitude is point 1 * If one latitude is a nan, then it becomes lat1. */ swapp = fabs(lat1) < fabs(lat2) ? -1 : 1; if (swapp < 0) { lonsign *= -1; swapx(&lat1, &lat2); } /* Make lat1 <= 0 */ latsign = lat1 < 0 ? 1 : -1; lat1 *= latsign; lat2 *= latsign; /* Now we have * * 0 <= lon12 <= 180 * -90 <= lat1 <= 0 * lat1 <= lat2 <= -lat1 * * longsign, swapp, latsign register the transformation to bring the * coordinates to this canonical form. In all cases, 1 means no change was * made. We make these transformations so that there are few cases to * check, e.g., on verifying quadrants in atan2. In addition, this * enforces some symmetries in the results returned. */ sincosdx(lat1, &sbet1, &cbet1); sbet1 *= g->f1; /* Ensure cbet1 = +epsilon at poles */ norm2(&sbet1, &cbet1); cbet1 = maxx(tiny, cbet1); sincosdx(lat2, &sbet2, &cbet2); sbet2 *= g->f1; /* Ensure cbet2 = +epsilon at poles */ norm2(&sbet2, &cbet2); cbet2 = maxx(tiny, cbet2); /* If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the * |bet1| - |bet2|. Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1 is * a better measure. This logic is used in assigning calp2 in Lambda12. * Sometimes these quantities vanish and in that case we force bet2 = +/- * bet1 exactly. An example where is is necessary is the inverse problem * 48.522876735459 0 -48.52287673545898293 179.599720456223079643 * which failed with Visual Studio 10 (Release and Debug) */ if (cbet1 < -sbet1) { if (cbet2 == cbet1) sbet2 = sbet2 < 0 ? sbet1 : -sbet1; } else { if (fabs(sbet2) == -sbet1) cbet2 = cbet1; } dn1 = sqrt(1 + g->ep2 * sq(sbet1)); dn2 = sqrt(1 + g->ep2 * sq(sbet2)); meridian = lat1 == -90 || slam12 == 0; if (meridian) { /* Endpoints are on a single full meridian, so the geodesic might lie on * a meridian. */ real ssig1, csig1, ssig2, csig2; calp1 = clam12; salp1 = slam12; /* Head to the target longitude */ calp2 = 1; salp2 = 0; /* At the target we're heading north */ /* tan(bet) = tan(sig) * cos(alp) */ ssig1 = sbet1; csig1 = calp1 * cbet1; ssig2 = sbet2; csig2 = calp2 * cbet2; /* sig12 = sig2 - sig1 */ sig12 = atan2(maxx((real)(0), csig1 * ssig2 - ssig1 * csig2), csig1 * csig2 + ssig1 * ssig2); Lengths(g, g->n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2, &s12x, &m12x, nullptr, (outmask & GEOD_GEODESICSCALE) ? &M12 : nullptr, (outmask & GEOD_GEODESICSCALE) ? &M21 : nullptr, Ca); /* Add the check for sig12 since zero length geodesics might yield m12 < * 0. Test case was * * echo 20.001 0 20.001 0 | GeodSolve -i * * In fact, we will have sig12 > pi/2 for meridional geodesic which is * not a shortest path. */ if (sig12 < 1 || m12x >= 0) { /* Need at least 2, to handle 90 0 90 180 */ if (sig12 < 3 * tiny || // Prevent negative s12 or m12 for short lines (sig12 < tol0 && (s12x < 0 || m12x < 0))) sig12 = m12x = s12x = 0; m12x *= g->b; s12x *= g->b; a12 = sig12 / degree; } else /* m12 < 0, i.e., prolate and too close to anti-podal */ meridian = FALSE; } if (!meridian && sbet1 == 0 && /* and sbet2 == 0 */ /* Mimic the way Lambda12 works with calp1 = 0 */ (g->f <= 0 || lon12s >= g->f * 180)) { /* Geodesic runs along equator */ calp1 = calp2 = 0; salp1 = salp2 = 1; s12x = g->a * lam12; sig12 = omg12 = lam12 / g->f1; m12x = g->b * sin(sig12); if (outmask & GEOD_GEODESICSCALE) M12 = M21 = cos(sig12); a12 = lon12 / g->f1; } else if (!meridian) { /* Now point1 and point2 belong within a hemisphere bounded by a * meridian and geodesic is neither meridional or equatorial. */ /* Figure a starting point for Newton's method */ real dnm = 0; sig12 = InverseStart(g, sbet1, cbet1, dn1, sbet2, cbet2, dn2, lam12, slam12, clam12, &salp1, &calp1, &salp2, &calp2, &dnm, Ca); if (sig12 >= 0) { /* Short lines (InverseStart sets salp2, calp2, dnm) */ s12x = sig12 * g->b * dnm; m12x = sq(dnm) * g->b * sin(sig12 / dnm); if (outmask & GEOD_GEODESICSCALE) M12 = M21 = cos(sig12 / dnm); a12 = sig12 / degree; omg12 = lam12 / (g->f1 * dnm); } else { /* Newton's method. This is a straightforward solution of f(alp1) = * lambda12(alp1) - lam12 = 0 with one wrinkle. f(alp) has exactly one * root in the interval (0, pi) and its derivative is positive at the * root. Thus f(alp) is positive for alp > alp1 and negative for alp < * alp1. During the course of the iteration, a range (alp1a, alp1b) is * maintained which brackets the root and with each evaluation of * f(alp) the range is shrunk, if possible. Newton's method is * restarted whenever the derivative of f is negative (because the new * value of alp1 is then further from the solution) or if the new * estimate of alp1 lies outside (0,pi); in this case, the new starting * guess is taken to be (alp1a + alp1b) / 2. */ real ssig1 = 0, csig1 = 0, ssig2 = 0, csig2 = 0, eps = 0, domg12 = 0; unsigned numit = 0; /* Bracketing range */ real salp1a = tiny, calp1a = 1, salp1b = tiny, calp1b = -1; boolx tripn = FALSE; boolx tripb = FALSE; for (; numit < maxit2; ++numit) { /* the WGS84 test set: mean = 1.47, sd = 1.25, max = 16 * WGS84 and random input: mean = 2.85, sd = 0.60 */ real dv = 0, v = Lambda12(g, sbet1, cbet1, dn1, sbet2, cbet2, dn2, salp1, calp1, slam12, clam12, &salp2, &calp2, &sig12, &ssig1, &csig1, &ssig2, &csig2, &eps, &domg12, numit < maxit1, &dv, Ca); /* Reversed test to allow escape with NaNs */ if (tripb || !(fabs(v) >= (tripn ? 8 : 1) * tol0)) break; /* Update bracketing values */ if (v > 0 && (numit > maxit1 || calp1/salp1 > calp1b/salp1b)) { salp1b = salp1; calp1b = calp1; } else if (v < 0 && (numit > maxit1 || calp1/salp1 < calp1a/salp1a)) { salp1a = salp1; calp1a = calp1; } if (numit < maxit1 && dv > 0) { real dalp1 = -v/dv; real sdalp1 = sin(dalp1), cdalp1 = cos(dalp1), nsalp1 = salp1 * cdalp1 + calp1 * sdalp1; if (nsalp1 > 0 && fabs(dalp1) < pi) { calp1 = calp1 * cdalp1 - salp1 * sdalp1; salp1 = nsalp1; norm2(&salp1, &calp1); /* In some regimes we don't get quadratic convergence because * slope -> 0. So use convergence conditions based on epsilon * instead of sqrt(epsilon). */ tripn = fabs(v) <= 16 * tol0; continue; } } /* Either dv was not positive or updated value was outside legal * range. Use the midpoint of the bracket as the next estimate. * This mechanism is not needed for the WGS84 ellipsoid, but it does * catch problems with more eccentric ellipsoids. Its efficacy is * such for the WGS84 test set with the starting guess set to alp1 = * 90deg: * the WGS84 test set: mean = 5.21, sd = 3.93, max = 24 * WGS84 and random input: mean = 4.74, sd = 0.99 */ salp1 = (salp1a + salp1b)/2; calp1 = (calp1a + calp1b)/2; norm2(&salp1, &calp1); tripn = FALSE; tripb = (fabs(salp1a - salp1) + (calp1a - calp1) < tolb || fabs(salp1 - salp1b) + (calp1 - calp1b) < tolb); } Lengths(g, eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2, &s12x, &m12x, nullptr, (outmask & GEOD_GEODESICSCALE) ? &M12 : nullptr, (outmask & GEOD_GEODESICSCALE) ? &M21 : nullptr, Ca); m12x *= g->b; s12x *= g->b; a12 = sig12 / degree; if (outmask & GEOD_AREA) { /* omg12 = lam12 - domg12 */ real sdomg12 = sin(domg12), cdomg12 = cos(domg12); somg12 = slam12 * cdomg12 - clam12 * sdomg12; comg12 = clam12 * cdomg12 + slam12 * sdomg12; } } } if (outmask & GEOD_DISTANCE) s12 = 0 + s12x; /* Convert -0 to 0 */ if (outmask & GEOD_REDUCEDLENGTH) m12 = 0 + m12x; /* Convert -0 to 0 */ if (outmask & GEOD_AREA) { real /* From Lambda12: sin(alp1) * cos(bet1) = sin(alp0) */ salp0 = salp1 * cbet1, calp0 = hypot(calp1, salp1 * sbet1); /* calp0 > 0 */ real alp12; if (calp0 != 0 && salp0 != 0) { real /* From Lambda12: tan(bet) = tan(sig) * cos(alp) */ ssig1 = sbet1, csig1 = calp1 * cbet1, ssig2 = sbet2, csig2 = calp2 * cbet2, k2 = sq(calp0) * g->ep2, eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2), /* Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0). */ A4 = sq(g->a) * calp0 * salp0 * g->e2; real B41, B42; norm2(&ssig1, &csig1); norm2(&ssig2, &csig2); C4f(g, eps, Ca); B41 = SinCosSeries(FALSE, ssig1, csig1, Ca, nC4); B42 = SinCosSeries(FALSE, ssig2, csig2, Ca, nC4); S12 = A4 * (B42 - B41); } else /* Avoid problems with indeterminate sig1, sig2 on equator */ S12 = 0; if (!meridian && somg12 > 1) { somg12 = sin(omg12); comg12 = cos(omg12); } if (!meridian && /* omg12 < 3/4 * pi */ comg12 > -(real)(0.7071) && /* Long difference not too big */ sbet2 - sbet1 < (real)(1.75)) { /* Lat difference not too big */ /* Use tan(Gamma/2) = tan(omg12/2) * * (tan(bet1/2)+tan(bet2/2))/(1+tan(bet1/2)*tan(bet2/2)) * with tan(x/2) = sin(x)/(1+cos(x)) */ real domg12 = 1 + comg12, dbet1 = 1 + cbet1, dbet2 = 1 + cbet2; alp12 = 2 * atan2( somg12 * ( sbet1 * dbet2 + sbet2 * dbet1 ), domg12 * ( sbet1 * sbet2 + dbet1 * dbet2 ) ); } else { /* alp12 = alp2 - alp1, used in atan2 so no need to normalize */ real salp12 = salp2 * calp1 - calp2 * salp1, calp12 = calp2 * calp1 + salp2 * salp1; /* The right thing appears to happen if alp1 = +/-180 and alp2 = 0, viz * salp12 = -0 and alp12 = -180. However this depends on the sign * being attached to 0 correctly. The following ensures the correct * behavior. */ if (salp12 == 0 && calp12 < 0) { salp12 = tiny * calp1; calp12 = -1; } alp12 = atan2(salp12, calp12); } S12 += g->c2 * alp12; S12 *= swapp * lonsign * latsign; /* Convert -0 to 0 */ S12 += 0; } /* Convert calp, salp to azimuth accounting for lonsign, swapp, latsign. */ if (swapp < 0) { swapx(&salp1, &salp2); swapx(&calp1, &calp2); if (outmask & GEOD_GEODESICSCALE) swapx(&M12, &M21); } salp1 *= swapp * lonsign; calp1 *= swapp * latsign; salp2 *= swapp * lonsign; calp2 *= swapp * latsign; if (psalp1) *psalp1 = salp1; if (pcalp1) *pcalp1 = calp1; if (psalp2) *psalp2 = salp2; if (pcalp2) *pcalp2 = calp2; if (outmask & GEOD_DISTANCE) *ps12 = s12; if (outmask & GEOD_REDUCEDLENGTH) *pm12 = m12; if (outmask & GEOD_GEODESICSCALE) { if (pM12) *pM12 = M12; if (pM21) *pM21 = M21; } if (outmask & GEOD_AREA) *pS12 = S12; /* Returned value in [0, 180] */ return a12; } real geod_geninverse(const struct geod_geodesic* g, real lat1, real lon1, real lat2, real lon2, real* ps12, real* pazi1, real* pazi2, real* pm12, real* pM12, real* pM21, real* pS12) { real salp1, calp1, salp2, calp2, a12 = geod_geninverse_int(g, lat1, lon1, lat2, lon2, ps12, &salp1, &calp1, &salp2, &calp2, pm12, pM12, pM21, pS12); if (pazi1) *pazi1 = atan2dx(salp1, calp1); if (pazi2) *pazi2 = atan2dx(salp2, calp2); return a12; } void geod_inverseline(struct geod_geodesicline* l, const struct geod_geodesic* g, real lat1, real lon1, real lat2, real lon2, unsigned caps) { real salp1, calp1, a12 = geod_geninverse_int(g, lat1, lon1, lat2, lon2, nullptr, &salp1, &calp1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr), azi1 = atan2dx(salp1, calp1); caps = caps ? caps : GEOD_DISTANCE_IN | GEOD_LONGITUDE; /* Ensure that a12 can be converted to a distance */ if (caps & (OUT_ALL & GEOD_DISTANCE_IN)) caps |= GEOD_DISTANCE; geod_lineinit_int(l, g, lat1, lon1, azi1, salp1, calp1, caps); geod_setarc(l, a12); } void geod_inverse(const struct geod_geodesic* g, real lat1, real lon1, real lat2, real lon2, real* ps12, real* pazi1, real* pazi2) { geod_geninverse(g, lat1, lon1, lat2, lon2, ps12, pazi1, pazi2, nullptr, nullptr, nullptr, nullptr); } real SinCosSeries(boolx sinp, real sinx, real cosx, const real c[], int n) { /* Evaluate * y = sinp ? sum(c[i] * sin( 2*i * x), i, 1, n) : * sum(c[i] * cos((2*i+1) * x), i, 0, n-1) * using Clenshaw summation. N.B. c[0] is unused for sin series * Approx operation count = (n + 5) mult and (2 * n + 2) add */ real ar, y0, y1; c += (n + sinp); /* Point to one beyond last element */ ar = 2 * (cosx - sinx) * (cosx + sinx); /* 2 * cos(2 * x) */ y0 = (n & 1) ? *--c : 0; y1 = 0; /* accumulators for sum */ /* Now n is even */ n /= 2; while (n--) { /* Unroll loop x 2, so accumulators return to their original role */ y1 = ar * y0 - y1 + *--c; y0 = ar * y1 - y0 + *--c; } return sinp ? 2 * sinx * cosx * y0 /* sin(2 * x) * y0 */ : cosx * (y0 - y1); /* cos(x) * (y0 - y1) */ } void Lengths(const struct geod_geodesic* g, real eps, real sig12, real ssig1, real csig1, real dn1, real ssig2, real csig2, real dn2, real cbet1, real cbet2, real* ps12b, real* pm12b, real* pm0, real* pM12, real* pM21, /* Scratch area of the right size */ real Ca[]) { real m0 = 0, J12 = 0, A1 = 0, A2 = 0; real Cb[nC]; /* Return m12b = (reduced length)/b; also calculate s12b = distance/b, * and m0 = coefficient of secular term in expression for reduced length. */ boolx redlp = pm12b || pm0 || pM12 || pM21; if (ps12b || redlp) { A1 = A1m1f(eps); C1f(eps, Ca); if (redlp) { A2 = A2m1f(eps); C2f(eps, Cb); m0 = A1 - A2; A2 = 1 + A2; } A1 = 1 + A1; } if (ps12b) { real B1 = SinCosSeries(TRUE, ssig2, csig2, Ca, nC1) - SinCosSeries(TRUE, ssig1, csig1, Ca, nC1); /* Missing a factor of b */ *ps12b = A1 * (sig12 + B1); if (redlp) { real B2 = SinCosSeries(TRUE, ssig2, csig2, Cb, nC2) - SinCosSeries(TRUE, ssig1, csig1, Cb, nC2); J12 = m0 * sig12 + (A1 * B1 - A2 * B2); } } else if (redlp) { /* Assume here that nC1 >= nC2 */ int l; for (l = 1; l <= nC2; ++l) Cb[l] = A1 * Ca[l] - A2 * Cb[l]; J12 = m0 * sig12 + (SinCosSeries(TRUE, ssig2, csig2, Cb, nC2) - SinCosSeries(TRUE, ssig1, csig1, Cb, nC2)); } if (pm0) *pm0 = m0; if (pm12b) /* Missing a factor of b. * Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure * accurate cancellation in the case of coincident points. */ *pm12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) - csig1 * csig2 * J12; if (pM12 || pM21) { real csig12 = csig1 * csig2 + ssig1 * ssig2; real t = g->ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2); if (pM12) *pM12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1; if (pM21) *pM21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2; } } real Astroid(real x, real y) { /* Solve k^4+2*k^3-(x^2+y^2-1)*k^2-2*y^2*k-y^2 = 0 for positive root k. * This solution is adapted from Geocentric::Reverse. */ real k; real p = sq(x), q = sq(y), r = (p + q - 1) / 6; if ( !(q == 0 && r <= 0) ) { real /* Avoid possible division by zero when r = 0 by multiplying equations * for s and t by r^3 and r, resp. */ S = p * q / 4, /* S = r^3 * s */ r2 = sq(r), r3 = r * r2, /* The discriminant of the quadratic equation for T3. This is zero on * the evolute curve p^(1/3)+q^(1/3) = 1 */ disc = S * (S + 2 * r3); real u = r; real v, uv, w; if (disc >= 0) { real T3 = S + r3, T; /* Pick the sign on the sqrt to maximize abs(T3). This minimizes loss * of precision due to cancellation. The result is unchanged because * of the way the T is used in definition of u. */ T3 += T3 < 0 ? -sqrt(disc) : sqrt(disc); /* T3 = (r * t)^3 */ /* N.B. cbrt always returns the real root. cbrt(-8) = -2. */ T = cbrt(T3); /* T = r * t */ /* T can be zero; but then r2 / T -> 0. */ u += T + (T != 0 ? r2 / T : 0); } else { /* T is complex, but the way u is defined the result is real. */ real ang = atan2(sqrt(-disc), -(S + r3)); /* There are three possible cube roots. We choose the root which * avoids cancellation. Note that disc < 0 implies that r < 0. */ u += 2 * r * cos(ang / 3); } v = sqrt(sq(u) + q); /* guaranteed positive */ /* Avoid loss of accuracy when u < 0. */ uv = u < 0 ? q / (v - u) : u + v; /* u+v, guaranteed positive */ w = (uv - q) / (2 * v); /* positive? */ /* Rearrange expression for k to avoid loss of accuracy due to * subtraction. Division by 0 not possible because uv > 0, w >= 0. */ k = uv / (sqrt(uv + sq(w)) + w); /* guaranteed positive */ } else { /* q == 0 && r <= 0 */ /* y = 0 with |x| <= 1. Handle this case directly. * for y small, positive root is k = abs(y)/sqrt(1-x^2) */ k = 0; } return k; } real InverseStart(const struct geod_geodesic* g, real sbet1, real cbet1, real dn1, real sbet2, real cbet2, real dn2, real lam12, real slam12, real clam12, real* psalp1, real* pcalp1, /* Only updated if return val >= 0 */ real* psalp2, real* pcalp2, /* Only updated for short lines */ real* pdnm, /* Scratch area of the right size */ real Ca[]) { real salp1 = 0, calp1 = 0, salp2 = 0, calp2 = 0, dnm = 0; /* Return a starting point for Newton's method in salp1 and calp1 (function * value is -1). If Newton's method doesn't need to be used, return also * salp2 and calp2 and function value is sig12. */ real sig12 = -1, /* Return value */ /* bet12 = bet2 - bet1 in [0, pi); bet12a = bet2 + bet1 in (-pi, 0] */ sbet12 = sbet2 * cbet1 - cbet2 * sbet1, cbet12 = cbet2 * cbet1 + sbet2 * sbet1; real sbet12a; boolx shortline = cbet12 >= 0 && sbet12 < (real)(0.5) && cbet2 * lam12 < (real)(0.5); real somg12, comg12, ssig12, csig12; sbet12a = sbet2 * cbet1 + cbet2 * sbet1; if (shortline) { real sbetm2 = sq(sbet1 + sbet2), omg12; /* sin((bet1+bet2)/2)^2 * = (sbet1 + sbet2)^2 / ((sbet1 + sbet2)^2 + (cbet1 + cbet2)^2) */ sbetm2 /= sbetm2 + sq(cbet1 + cbet2); dnm = sqrt(1 + g->ep2 * sbetm2); omg12 = lam12 / (g->f1 * dnm); somg12 = sin(omg12); comg12 = cos(omg12); } else { somg12 = slam12; comg12 = clam12; } salp1 = cbet2 * somg12; calp1 = comg12 >= 0 ? sbet12 + cbet2 * sbet1 * sq(somg12) / (1 + comg12) : sbet12a - cbet2 * sbet1 * sq(somg12) / (1 - comg12); ssig12 = hypot(salp1, calp1); csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12; if (shortline && ssig12 < g->etol2) { /* really short lines */ salp2 = cbet1 * somg12; calp2 = sbet12 - cbet1 * sbet2 * (comg12 >= 0 ? sq(somg12) / (1 + comg12) : 1 - comg12); norm2(&salp2, &calp2); /* Set return value */ sig12 = atan2(ssig12, csig12); } else if (fabs(g->n) > (real)(0.1) || /* No astroid calc if too eccentric */ csig12 >= 0 || ssig12 >= 6 * fabs(g->n) * pi * sq(cbet1)) { /* Nothing to do, zeroth order spherical approximation is OK */ } else { /* Scale lam12 and bet2 to x, y coordinate system where antipodal point * is at origin and singular point is at y = 0, x = -1. */ real y, lamscale, betscale; /* Volatile declaration needed to fix inverse case * 56.320923501171 0 -56.320923501171 179.664747671772880215 * which otherwise fails with g++ 4.4.4 x86 -O3 */ volatile real x; real lam12x = atan2(-slam12, -clam12); /* lam12 - pi */ if (g->f >= 0) { /* In fact f == 0 does not get here */ /* x = dlong, y = dlat */ { real k2 = sq(sbet1) * g->ep2, eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2); lamscale = g->f * cbet1 * A3f(g, eps) * pi; } betscale = lamscale * cbet1; x = lam12x / lamscale; y = sbet12a / betscale; } else { /* f < 0 */ /* x = dlat, y = dlong */ real cbet12a = cbet2 * cbet1 - sbet2 * sbet1, bet12a = atan2(sbet12a, cbet12a); real m12b, m0; /* In the case of lon12 = 180, this repeats a calculation made in * Inverse. */ Lengths(g, g->n, pi + bet12a, sbet1, -cbet1, dn1, sbet2, cbet2, dn2, cbet1, cbet2, nullptr, &m12b, &m0, nullptr, nullptr, Ca); x = -1 + m12b / (cbet1 * cbet2 * m0 * pi); betscale = x < -(real)(0.01) ? sbet12a / x : -g->f * sq(cbet1) * pi; lamscale = betscale / cbet1; y = lam12x / lamscale; } if (y > -tol1 && x > -1 - xthresh) { /* strip near cut */ if (g->f >= 0) { salp1 = minx((real)(1), -(real)(x)); calp1 = - sqrt(1 - sq(salp1)); } else { calp1 = maxx((real)(x > -tol1 ? 0 : -1), (real)(x)); salp1 = sqrt(1 - sq(calp1)); } } else { /* Estimate alp1, by solving the astroid problem. * * Could estimate alpha1 = theta + pi/2, directly, i.e., * calp1 = y/k; salp1 = -x/(1+k); for f >= 0 * calp1 = x/(1+k); salp1 = -y/k; for f < 0 (need to check) * * However, it's better to estimate omg12 from astroid and use * spherical formula to compute alp1. This reduces the mean number of * Newton iterations for astroid cases from 2.24 (min 0, max 6) to 2.12 * (min 0 max 5). The changes in the number of iterations are as * follows: * * change percent * 1 5 * 0 78 * -1 16 * -2 0.6 * -3 0.04 * -4 0.002 * * The histogram of iterations is (m = number of iterations estimating * alp1 directly, n = number of iterations estimating via omg12, total * number of trials = 148605): * * iter m n * 0 148 186 * 1 13046 13845 * 2 93315 102225 * 3 36189 32341 * 4 5396 7 * 5 455 1 * 6 56 0 * * Because omg12 is near pi, estimate work with omg12a = pi - omg12 */ real k = Astroid(x, y); real omg12a = lamscale * ( g->f >= 0 ? -x * k/(1 + k) : -y * (1 + k)/k ); somg12 = sin(omg12a); comg12 = -cos(omg12a); /* Update spherical estimate of alp1 using omg12 instead of lam12 */ salp1 = cbet2 * somg12; calp1 = sbet12a - cbet2 * sbet1 * sq(somg12) / (1 - comg12); } } /* Sanity check on starting guess. Backwards check allows NaN through. */ if (!(salp1 <= 0)) norm2(&salp1, &calp1); else { salp1 = 1; calp1 = 0; } *psalp1 = salp1; *pcalp1 = calp1; if (shortline) *pdnm = dnm; if (sig12 >= 0) { *psalp2 = salp2; *pcalp2 = calp2; } return sig12; } real Lambda12(const struct geod_geodesic* g, real sbet1, real cbet1, real dn1, real sbet2, real cbet2, real dn2, real salp1, real calp1, real slam120, real clam120, real* psalp2, real* pcalp2, real* psig12, real* pssig1, real* pcsig1, real* pssig2, real* pcsig2, real* peps, real* pdomg12, boolx diffp, real* pdlam12, /* Scratch area of the right size */ real Ca[]) { real salp2 = 0, calp2 = 0, sig12 = 0, ssig1 = 0, csig1 = 0, ssig2 = 0, csig2 = 0, eps = 0, domg12 = 0, dlam12 = 0; real salp0, calp0; real somg1, comg1, somg2, comg2, somg12, comg12, lam12; real B312, eta, k2; if (sbet1 == 0 && calp1 == 0) /* Break degeneracy of equatorial line. This case has already been * handled. */ calp1 = -tiny; /* sin(alp1) * cos(bet1) = sin(alp0) */ salp0 = salp1 * cbet1; calp0 = hypot(calp1, salp1 * sbet1); /* calp0 > 0 */ /* tan(bet1) = tan(sig1) * cos(alp1) * tan(omg1) = sin(alp0) * tan(sig1) = tan(omg1)=tan(alp1)*sin(bet1) */ ssig1 = sbet1; somg1 = salp0 * sbet1; csig1 = comg1 = calp1 * cbet1; norm2(&ssig1, &csig1); /* norm2(&somg1, &comg1); -- don't need to normalize! */ /* Enforce symmetries in the case abs(bet2) = -bet1. Need to be careful * about this case, since this can yield singularities in the Newton * iteration. * sin(alp2) * cos(bet2) = sin(alp0) */ salp2 = cbet2 != cbet1 ? salp0 / cbet2 : salp1; /* calp2 = sqrt(1 - sq(salp2)) * = sqrt(sq(calp0) - sq(sbet2)) / cbet2 * and subst for calp0 and rearrange to give (choose positive sqrt * to give alp2 in [0, pi/2]). */ calp2 = cbet2 != cbet1 || fabs(sbet2) != -sbet1 ? sqrt(sq(calp1 * cbet1) + (cbet1 < -sbet1 ? (cbet2 - cbet1) * (cbet1 + cbet2) : (sbet1 - sbet2) * (sbet1 + sbet2))) / cbet2 : fabs(calp1); /* tan(bet2) = tan(sig2) * cos(alp2) * tan(omg2) = sin(alp0) * tan(sig2). */ ssig2 = sbet2; somg2 = salp0 * sbet2; csig2 = comg2 = calp2 * cbet2; norm2(&ssig2, &csig2); /* norm2(&somg2, &comg2); -- don't need to normalize! */ /* sig12 = sig2 - sig1, limit to [0, pi] */ sig12 = atan2(maxx((real)(0), csig1 * ssig2 - ssig1 * csig2), csig1 * csig2 + ssig1 * ssig2); /* omg12 = omg2 - omg1, limit to [0, pi] */ somg12 = maxx((real)(0), comg1 * somg2 - somg1 * comg2); comg12 = comg1 * comg2 + somg1 * somg2; /* eta = omg12 - lam120 */ eta = atan2(somg12 * clam120 - comg12 * slam120, comg12 * clam120 + somg12 * slam120); k2 = sq(calp0) * g->ep2; eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2); C3f(g, eps, Ca); B312 = (SinCosSeries(TRUE, ssig2, csig2, Ca, nC3-1) - SinCosSeries(TRUE, ssig1, csig1, Ca, nC3-1)); domg12 = -g->f * A3f(g, eps) * salp0 * (sig12 + B312); lam12 = eta + domg12; if (diffp) { if (calp2 == 0) dlam12 = - 2 * g->f1 * dn1 / sbet1; else { Lengths(g, eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2, nullptr, &dlam12, nullptr, nullptr, nullptr, Ca); dlam12 *= g->f1 / (calp2 * cbet2); } } *psalp2 = salp2; *pcalp2 = calp2; *psig12 = sig12; *pssig1 = ssig1; *pcsig1 = csig1; *pssig2 = ssig2; *pcsig2 = csig2; *peps = eps; *pdomg12 = domg12; if (diffp) *pdlam12 = dlam12; return lam12; } real A3f(const struct geod_geodesic* g, real eps) { /* Evaluate A3 */ return polyval(nA3 - 1, g->A3x, eps); } void C3f(const struct geod_geodesic* g, real eps, real c[]) { /* Evaluate C3 coeffs * Elements c[1] through c[nC3 - 1] are set */ real mult = 1; int o = 0, l; for (l = 1; l < nC3; ++l) { /* l is index of C3[l] */ int m = nC3 - l - 1; /* order of polynomial in eps */ mult *= eps; c[l] = mult * polyval(m, g->C3x + o, eps); o += m + 1; } } void C4f(const struct geod_geodesic* g, real eps, real c[]) { /* Evaluate C4 coeffs * Elements c[0] through c[nC4 - 1] are set */ real mult = 1; int o = 0, l; for (l = 0; l < nC4; ++l) { /* l is index of C4[l] */ int m = nC4 - l - 1; /* order of polynomial in eps */ c[l] = mult * polyval(m, g->C4x + o, eps); o += m + 1; mult *= eps; } } /* The scale factor A1-1 = mean value of (d/dsigma)I1 - 1 */ real A1m1f(real eps) { static const real coeff[] = { /* (1-eps)*A1-1, polynomial in eps2 of order 3 */ 1, 4, 64, 0, 256, }; int m = nA1/2; real t = polyval(m, coeff, sq(eps)) / coeff[m + 1]; return (t + eps) / (1 - eps); } /* The coefficients C1[l] in the Fourier expansion of B1 */ void C1f(real eps, real c[]) { static const real coeff[] = { /* C1[1]/eps^1, polynomial in eps2 of order 2 */ -1, 6, -16, 32, /* C1[2]/eps^2, polynomial in eps2 of order 2 */ -9, 64, -128, 2048, /* C1[3]/eps^3, polynomial in eps2 of order 1 */ 9, -16, 768, /* C1[4]/eps^4, polynomial in eps2 of order 1 */ 3, -5, 512, /* C1[5]/eps^5, polynomial in eps2 of order 0 */ -7, 1280, /* C1[6]/eps^6, polynomial in eps2 of order 0 */ -7, 2048, }; real eps2 = sq(eps), d = eps; int o = 0, l; for (l = 1; l <= nC1; ++l) { /* l is index of C1p[l] */ int m = (nC1 - l) / 2; /* order of polynomial in eps^2 */ c[l] = d * polyval(m, coeff + o, eps2) / coeff[o + m + 1]; o += m + 2; d *= eps; } } /* The coefficients C1p[l] in the Fourier expansion of B1p */ void C1pf(real eps, real c[]) { static const real coeff[] = { /* C1p[1]/eps^1, polynomial in eps2 of order 2 */ 205, -432, 768, 1536, /* C1p[2]/eps^2, polynomial in eps2 of order 2 */ 4005, -4736, 3840, 12288, /* C1p[3]/eps^3, polynomial in eps2 of order 1 */ -225, 116, 384, /* C1p[4]/eps^4, polynomial in eps2 of order 1 */ -7173, 2695, 7680, /* C1p[5]/eps^5, polynomial in eps2 of order 0 */ 3467, 7680, /* C1p[6]/eps^6, polynomial in eps2 of order 0 */ 38081, 61440, }; real eps2 = sq(eps), d = eps; int o = 0, l; for (l = 1; l <= nC1p; ++l) { /* l is index of C1p[l] */ int m = (nC1p - l) / 2; /* order of polynomial in eps^2 */ c[l] = d * polyval(m, coeff + o, eps2) / coeff[o + m + 1]; o += m + 2; d *= eps; } } /* The scale factor A2-1 = mean value of (d/dsigma)I2 - 1 */ real A2m1f(real eps) { static const real coeff[] = { /* (eps+1)*A2-1, polynomial in eps2 of order 3 */ -11, -28, -192, 0, 256, }; int m = nA2/2; real t = polyval(m, coeff, sq(eps)) / coeff[m + 1]; return (t - eps) / (1 + eps); } /* The coefficients C2[l] in the Fourier expansion of B2 */ void C2f(real eps, real c[]) { static const real coeff[] = { /* C2[1]/eps^1, polynomial in eps2 of order 2 */ 1, 2, 16, 32, /* C2[2]/eps^2, polynomial in eps2 of order 2 */ 35, 64, 384, 2048, /* C2[3]/eps^3, polynomial in eps2 of order 1 */ 15, 80, 768, /* C2[4]/eps^4, polynomial in eps2 of order 1 */ 7, 35, 512, /* C2[5]/eps^5, polynomial in eps2 of order 0 */ 63, 1280, /* C2[6]/eps^6, polynomial in eps2 of order 0 */ 77, 2048, }; real eps2 = sq(eps), d = eps; int o = 0, l; for (l = 1; l <= nC2; ++l) { /* l is index of C2[l] */ int m = (nC2 - l) / 2; /* order of polynomial in eps^2 */ c[l] = d * polyval(m, coeff + o, eps2) / coeff[o + m + 1]; o += m + 2; d *= eps; } } /* The scale factor A3 = mean value of (d/dsigma)I3 */ void A3coeff(struct geod_geodesic* g) { static const real coeff[] = { /* A3, coeff of eps^5, polynomial in n of order 0 */ -3, 128, /* A3, coeff of eps^4, polynomial in n of order 1 */ -2, -3, 64, /* A3, coeff of eps^3, polynomial in n of order 2 */ -1, -3, -1, 16, /* A3, coeff of eps^2, polynomial in n of order 2 */ 3, -1, -2, 8, /* A3, coeff of eps^1, polynomial in n of order 1 */ 1, -1, 2, /* A3, coeff of eps^0, polynomial in n of order 0 */ 1, 1, }; int o = 0, k = 0, j; for (j = nA3 - 1; j >= 0; --j) { /* coeff of eps^j */ int m = nA3 - j - 1 < j ? nA3 - j - 1 : j; /* order of polynomial in n */ g->A3x[k++] = polyval(m, coeff + o, g->n) / coeff[o + m + 1]; o += m + 2; } } /* The coefficients C3[l] in the Fourier expansion of B3 */ void C3coeff(struct geod_geodesic* g) { static const real coeff[] = { /* C3[1], coeff of eps^5, polynomial in n of order 0 */ 3, 128, /* C3[1], coeff of eps^4, polynomial in n of order 1 */ 2, 5, 128, /* C3[1], coeff of eps^3, polynomial in n of order 2 */ -1, 3, 3, 64, /* C3[1], coeff of eps^2, polynomial in n of order 2 */ -1, 0, 1, 8, /* C3[1], coeff of eps^1, polynomial in n of order 1 */ -1, 1, 4, /* C3[2], coeff of eps^5, polynomial in n of order 0 */ 5, 256, /* C3[2], coeff of eps^4, polynomial in n of order 1 */ 1, 3, 128, /* C3[2], coeff of eps^3, polynomial in n of order 2 */ -3, -2, 3, 64, /* C3[2], coeff of eps^2, polynomial in n of order 2 */ 1, -3, 2, 32, /* C3[3], coeff of eps^5, polynomial in n of order 0 */ 7, 512, /* C3[3], coeff of eps^4, polynomial in n of order 1 */ -10, 9, 384, /* C3[3], coeff of eps^3, polynomial in n of order 2 */ 5, -9, 5, 192, /* C3[4], coeff of eps^5, polynomial in n of order 0 */ 7, 512, /* C3[4], coeff of eps^4, polynomial in n of order 1 */ -14, 7, 512, /* C3[5], coeff of eps^5, polynomial in n of order 0 */ 21, 2560, }; int o = 0, k = 0, l, j; for (l = 1; l < nC3; ++l) { /* l is index of C3[l] */ for (j = nC3 - 1; j >= l; --j) { /* coeff of eps^j */ int m = nC3 - j - 1 < j ? nC3 - j - 1 : j; /* order of polynomial in n */ g->C3x[k++] = polyval(m, coeff + o, g->n) / coeff[o + m + 1]; o += m + 2; } } } /* The coefficients C4[l] in the Fourier expansion of I4 */ void C4coeff(struct geod_geodesic* g) { static const real coeff[] = { /* C4[0], coeff of eps^5, polynomial in n of order 0 */ 97, 15015, /* C4[0], coeff of eps^4, polynomial in n of order 1 */ 1088, 156, 45045, /* C4[0], coeff of eps^3, polynomial in n of order 2 */ -224, -4784, 1573, 45045, /* C4[0], coeff of eps^2, polynomial in n of order 3 */ -10656, 14144, -4576, -858, 45045, /* C4[0], coeff of eps^1, polynomial in n of order 4 */ 64, 624, -4576, 6864, -3003, 15015, /* C4[0], coeff of eps^0, polynomial in n of order 5 */ 100, 208, 572, 3432, -12012, 30030, 45045, /* C4[1], coeff of eps^5, polynomial in n of order 0 */ 1, 9009, /* C4[1], coeff of eps^4, polynomial in n of order 1 */ -2944, 468, 135135, /* C4[1], coeff of eps^3, polynomial in n of order 2 */ 5792, 1040, -1287, 135135, /* C4[1], coeff of eps^2, polynomial in n of order 3 */ 5952, -11648, 9152, -2574, 135135, /* C4[1], coeff of eps^1, polynomial in n of order 4 */ -64, -624, 4576, -6864, 3003, 135135, /* C4[2], coeff of eps^5, polynomial in n of order 0 */ 8, 10725, /* C4[2], coeff of eps^4, polynomial in n of order 1 */ 1856, -936, 225225, /* C4[2], coeff of eps^3, polynomial in n of order 2 */ -8448, 4992, -1144, 225225, /* C4[2], coeff of eps^2, polynomial in n of order 3 */ -1440, 4160, -4576, 1716, 225225, /* C4[3], coeff of eps^5, polynomial in n of order 0 */ -136, 63063, /* C4[3], coeff of eps^4, polynomial in n of order 1 */ 1024, -208, 105105, /* C4[3], coeff of eps^3, polynomial in n of order 2 */ 3584, -3328, 1144, 315315, /* C4[4], coeff of eps^5, polynomial in n of order 0 */ -128, 135135, /* C4[4], coeff of eps^4, polynomial in n of order 1 */ -2560, 832, 405405, /* C4[5], coeff of eps^5, polynomial in n of order 0 */ 128, 99099, }; int o = 0, k = 0, l, j; for (l = 0; l < nC4; ++l) { /* l is index of C4[l] */ for (j = nC4 - 1; j >= l; --j) { /* coeff of eps^j */ int m = nC4 - j - 1; /* order of polynomial in n */ g->C4x[k++] = polyval(m, coeff + o, g->n) / coeff[o + m + 1]; o += m + 2; } } } int transit(real lon1, real lon2) { real lon12; /* Return 1 or -1 if crossing prime meridian in east or west direction. * Otherwise return zero. */ /* Compute lon12 the same way as Geodesic::Inverse. */ lon1 = AngNormalize(lon1); lon2 = AngNormalize(lon2); lon12 = AngDiff(lon1, lon2, nullptr); return lon1 <= 0 && lon2 > 0 && lon12 > 0 ? 1 : (lon2 <= 0 && lon1 > 0 && lon12 < 0 ? -1 : 0); } int transitdirect(real lon1, real lon2) { /* Compute exactly the parity of int(ceil(lon2 / 360)) - int(ceil(lon1 / 360)) */ lon1 = remainder(lon1, (real)(720)); lon2 = remainder(lon2, (real)(720)); return ( (lon2 <= 0 && lon2 > -360 ? 1 : 0) - (lon1 <= 0 && lon1 > -360 ? 1 : 0) ); } void accini(real s[]) { /* Initialize an accumulator; this is an array with two elements. */ s[0] = s[1] = 0; } void acccopy(const real s[], real t[]) { /* Copy an accumulator; t = s. */ t[0] = s[0]; t[1] = s[1]; } void accadd(real s[], real y) { /* Add y to an accumulator. */ real u, z = sumx(y, s[1], &u); s[0] = sumx(z, s[0], &s[1]); if (s[0] == 0) s[0] = u; else s[1] = s[1] + u; } real accsum(const real s[], real y) { /* Return accumulator + y (but don't add to accumulator). */ real t[2]; acccopy(s, t); accadd(t, y); return t[0]; } void accneg(real s[]) { /* Negate an accumulator. */ s[0] = -s[0]; s[1] = -s[1]; } void accrem(real s[], real y) { /* Reduce to [-y/2, y/2]. */ s[0] = remainder(s[0], y); accadd(s, (real)(0)); } void geod_polygon_init(struct geod_polygon* p, boolx polylinep) { p->polyline = (polylinep != 0); geod_polygon_clear(p); } void geod_polygon_clear(struct geod_polygon* p) { p->lat0 = p->lon0 = p->lat = p->lon = NaN; accini(p->P); accini(p->A); p->num = p->crossings = 0; } void geod_polygon_addpoint(const struct geod_geodesic* g, struct geod_polygon* p, real lat, real lon) { lon = AngNormalize(lon); if (p->num == 0) { p->lat0 = p->lat = lat; p->lon0 = p->lon = lon; } else { real s12, S12 = 0; /* Initialize S12 to stop Visual Studio warning */ geod_geninverse(g, p->lat, p->lon, lat, lon, &s12, nullptr, nullptr, nullptr, nullptr, nullptr, p->polyline ? nullptr : &S12); accadd(p->P, s12); if (!p->polyline) { accadd(p->A, S12); p->crossings += transit(p->lon, lon); } p->lat = lat; p->lon = lon; } ++p->num; } void geod_polygon_addedge(const struct geod_geodesic* g, struct geod_polygon* p, real azi, real s) { if (p->num) { /* Do nothing is num is zero */ /* Initialize S12 to stop Visual Studio warning. Initialization of lat and * lon is to make CLang static analyzer happy. */ real lat = 0, lon = 0, S12 = 0; geod_gendirect(g, p->lat, p->lon, azi, GEOD_LONG_UNROLL, s, &lat, &lon, nullptr, nullptr, nullptr, nullptr, nullptr, p->polyline ? nullptr : &S12); accadd(p->P, s); if (!p->polyline) { accadd(p->A, S12); p->crossings += transitdirect(p->lon, lon); } p->lat = lat; p->lon = lon; ++p->num; } } unsigned geod_polygon_compute(const struct geod_geodesic* g, const struct geod_polygon* p, boolx reverse, boolx sign, real* pA, real* pP) { real s12, S12, t[2]; if (p->num < 2) { if (pP) *pP = 0; if (!p->polyline && pA) *pA = 0; return p->num; } if (p->polyline) { if (pP) *pP = p->P[0]; return p->num; } geod_geninverse(g, p->lat, p->lon, p->lat0, p->lon0, &s12, nullptr, nullptr, nullptr, nullptr, nullptr, &S12); if (pP) *pP = accsum(p->P, s12); acccopy(p->A, t); accadd(t, S12); if (pA) *pA = areareduceA(t, 4 * pi * g->c2, p->crossings + transit(p->lon, p->lon0), reverse, sign); return p->num; } unsigned geod_polygon_testpoint(const struct geod_geodesic* g, const struct geod_polygon* p, real lat, real lon, boolx reverse, boolx sign, real* pA, real* pP) { real perimeter, tempsum; int crossings, i; unsigned num = p->num + 1; if (num == 1) { if (pP) *pP = 0; if (!p->polyline && pA) *pA = 0; return num; } perimeter = p->P[0]; tempsum = p->polyline ? 0 : p->A[0]; crossings = p->crossings; for (i = 0; i < (p->polyline ? 1 : 2); ++i) { real s12, S12 = 0; /* Initialize S12 to stop Visual Studio warning */ geod_geninverse(g, i == 0 ? p->lat : lat, i == 0 ? p->lon : lon, i != 0 ? p->lat0 : lat, i != 0 ? p->lon0 : lon, &s12, nullptr, nullptr, nullptr, nullptr, nullptr, p->polyline ? nullptr : &S12); perimeter += s12; if (!p->polyline) { tempsum += S12; crossings += transit(i == 0 ? p->lon : lon, i != 0 ? p->lon0 : lon); } } if (pP) *pP = perimeter; if (p->polyline) return num; if (pA) *pA = areareduceB(tempsum, 4 * pi * g->c2, crossings, reverse, sign); return num; } unsigned geod_polygon_testedge(const struct geod_geodesic* g, const struct geod_polygon* p, real azi, real s, boolx reverse, boolx sign, real* pA, real* pP) { real perimeter, tempsum; int crossings; unsigned num = p->num + 1; if (num == 1) { /* we don't have a starting point! */ if (pP) *pP = NaN; if (!p->polyline && pA) *pA = NaN; return 0; } perimeter = p->P[0] + s; if (p->polyline) { if (pP) *pP = perimeter; return num; } tempsum = p->A[0]; crossings = p->crossings; { /* Initialization of lat, lon, and S12 is to make CLang static analyzer * happy. */ real lat = 0, lon = 0, s12, S12 = 0; geod_gendirect(g, p->lat, p->lon, azi, GEOD_LONG_UNROLL, s, &lat, &lon, nullptr, nullptr, nullptr, nullptr, nullptr, &S12); tempsum += S12; crossings += transitdirect(p->lon, lon); geod_geninverse(g, lat, lon, p->lat0, p->lon0, &s12, nullptr, nullptr, nullptr, nullptr, nullptr, &S12); perimeter += s12; tempsum += S12; crossings += transit(lon, p->lon0); } if (pP) *pP = perimeter; if (pA) *pA = areareduceB(tempsum, 4 * pi * g->c2, crossings, reverse, sign); return num; } void geod_polygonarea(const struct geod_geodesic* g, real lats[], real lons[], int n, real* pA, real* pP) { int i; struct geod_polygon p; geod_polygon_init(&p, FALSE); for (i = 0; i < n; ++i) geod_polygon_addpoint(g, &p, lats[i], lons[i]); geod_polygon_compute(g, &p, FALSE, TRUE, pA, pP); } real areareduceA(real area[], real area0, int crossings, boolx reverse, boolx sign) { accrem(area, area0); if (crossings & 1) accadd(area, (area[0] < 0 ? 1 : -1) * area0/2); /* area is with the clockwise sense. If !reverse convert to * counter-clockwise convention. */ if (!reverse) accneg(area); /* If sign put area in (-area0/2, area0/2], else put area in [0, area0) */ if (sign) { if (area[0] > area0/2) accadd(area, -area0); else if (area[0] <= -area0/2) accadd(area, +area0); } else { if (area[0] >= area0) accadd(area, -area0); else if (area[0] < 0) accadd(area, +area0); } return 0 + area[0]; } real areareduceB(real area, real area0, int crossings, boolx reverse, boolx sign) { area = remainder(area, area0); if (crossings & 1) area += (area < 0 ? 1 : -1) * area0/2; /* area is with the clockwise sense. If !reverse convert to * counter-clockwise convention. */ if (!reverse) area *= -1; /* If sign put area in (-area0/2, area0/2], else put area in [0, area0) */ if (sign) { if (area > area0/2) area -= area0; else if (area <= -area0/2) area += area0; } else { if (area >= area0) area -= area0; else if (area < 0) area += area0; } return 0 + area; } /** @endcond */ terra/src/ram.cpp0000644000175000017500000000300014201035750013561 0ustar nileshnilesh#ifdef _WIN32 #include #elif __linux__ #include "sys/types.h" #include "sys/sysinfo.h" #include #elif __APPLE__ #include #include #include #include #endif double availableRAM() { //https://stackoverflow.com/questions/38490320/how-to-query-amount-of-allocated-memory-on-linux-and-osx //https://stackoverflow.com/questions/63166/how-to-determine-cpu-and-memory-consumption-from-inside-a-process double ram = 1e+9; // return available RAM in number of double (8 byte) cells. #ifdef _WIN32 MEMORYSTATUSEX statex; statex.dwLength = sizeof(statex); GlobalMemoryStatusEx(&statex); ram = statex.ullAvailPhys; #elif __linux__ struct sysinfo memInfo; sysinfo (&memInfo); ram = memInfo.freeram; #elif __APPLE__ vm_size_t page_size; mach_port_t mach_port; mach_msg_type_number_t count; vm_statistics64_data_t vm_stats; mach_port = mach_host_self(); count = sizeof(vm_stats) / sizeof(natural_t); if (KERN_SUCCESS == host_page_size(mach_port, &page_size) && KERN_SUCCESS == host_statistics64(mach_port, HOST_VM_INFO, (host_info64_t)&vm_stats, &count)) { long long free_memory = ((int64_t)vm_stats.free_count + (int64_t)vm_stats.inactive_count) * (int64_t)page_size; ram = free_memory; //https://stackoverflow.com/questions/63166/how-to-determine-cpu-and-memory-consumption-from-inside-a-process } #endif return ram / 8; // 8 bytes for each double } terra/src/write_gdal.cpp0000644000175000017500000006004614201035750015140 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include "spatRaster.h" #include "math_utils.h" #include "string_utils.h" #include "file_utils.h" #include "vecmath.h" #include #include #include "gdal_priv.h" #include "cpl_conv.h" // for CPLMalloc() #include "cpl_string.h" #include "ogr_spatialref.h" #include "gdal_rat.h" #include "gdalio.h" /* void add_quotes(std::vector &s) { for (size_t i=0; i< s.size(); i++) { s[i] = "\"" + s[i] + "\""; } } */ std::string quoted_csv(const std::vector &s) { std::string ss; if (s.size() == 0) { ss = ""; return ss; } ss = "\"" + s[0] + "\""; for (size_t i=1; i< s.size(); i++) { ss += ",\"" + s[i] + "\""; } return ss; } bool SpatRaster::write_aux_json(std::string filename) { filename += ".aux.json"; std::ofstream f; bool wunits = hasUnit(); bool wtime = hasTime(); if (wunits || wtime) { f.open(filename); if (f.is_open()) { f << "{" << std::endl; if (wtime) { std::vector tstr = getTimeStr(false); std::string ss = quoted_csv(tstr); f << "\"time\":[" << ss << "]," << std::endl; f << "\"timestep\":\"" << source[0].timestep << "\""; if (wunits) f << ","; f << std::endl; } if (wunits) { std::vector units = getUnit(); std::string ss = quoted_csv(units); f << "\"unit\":[" << ss << "]" << std::endl; } f << "}" << std::endl; } else { return false; } return true; } return true; } bool setRat(GDALRasterBand *poBand, SpatDataFrame &d) { // GDALRasterAttributeTable *pRat = poBand->GetDefaultRAT(); GDALRasterAttributeTable *pRat = new GDALDefaultRasterAttributeTable(); size_t nr = d.nrow(); for (size_t i=0; iCreateColumn(fn, GFT_Real, GFU_Generic) != CE_None) { return false; }; } else if (d.itype[i] == 1) { if (pRat->CreateColumn(fn, GFT_Integer, GFU_Generic) != CE_None) { return false; } } else { if (pRat->CreateColumn(fn, GFT_String, GFU_Generic) != CE_None) { return false; } } } pRat->SetRowCount(nr); for (size_t i=0; i v = d.dv[d.iplace[i]]; if( pRat->ValuesIO(GF_Write, i, 0, nr, &v[0]) != CE_None ) { return false; } } else if (d.itype[i] == 1) { std::vector v = d.iv[d.iplace[i]]; for (size_t j=0; jSetValue(j, i, (int)v[j]); } } else { std::vector v = d.sv[d.iplace[i]]; for (size_t j=0; jSetValue(j, i, v[j].c_str()); } } } CPLErr err = poBand->SetDefaultRAT(pRat); delete pRat; return (err == CE_None); } bool is_rat(SpatDataFrame &d) { if (d.nrow() == 0) return false; if (d.ncol() > 2) return true; if (d.itype[0] == 1) { long dmin = vmin(d.iv[0], true); long dmax = vmax(d.iv[0], true); if (dmin >= 0 && dmax <= 255) { return false; } } else if (d.itype[0] == 0) { double dmin = vmin(d.dv[0], true); double dmax = vmax(d.dv[0], true); if (dmin >= 0 && dmax <= 255) { return false; } } return true; } /* bool setCats(GDALRasterBand *poBand, std::vector &labels) { char **labs = NULL; for (size_t i = 0; i < labels.size(); i++) { labs = CSLAddString(labs, labels[i].c_str()); } CPLErr err = poBand->SetCategoryNames(labs); return (err == CE_None); } */ bool setBandCategories(GDALRasterBand *poBand, std::vector value, std::vector labs) { if (labs.size() != value.size()) return false; if (vmin(value, false) < 0) return false; if (vmax(value, false) > 255) return false; std::vector s(256, ""); for (size_t i=0; iSetCategoryNames(slabs); return (err == CE_None); } bool setCT(GDALRasterBand *poBand, SpatDataFrame &d) { if (d.ncol() < 5) return false; if (d.itype[0] != 1) return false; if (d.itype[1] != 1) return false; if (d.itype[2] != 1) return false; if (d.itype[3] != 1) return false; if (d.itype[4] != 1) return false; long dmin = vmin(d.iv[0], true); long dmax = vmax(d.iv[0], true); if (dmin < 0 || dmax > 255) { return false; } SpatDataFrame s; s.add_column(1, "red"); s.add_column(1, "green"); s.add_column(1, "blue"); s.add_column(1, "alpha"); s.resize_rows(256); for (size_t i=0; iSetColorInterpretation(GCI_PaletteIndex); if (err != CE_None) { return false; } GDALColorTable *poCT = new GDALColorTable(GPI_RGB); GDALColorEntry col; for (size_t j=0; j< s.nrow(); j++) { if (s.iv[3][j] == 0) { // maintain transparency in gtiff col.c1 = 255; col.c2 = 255; col.c3 = 255; col.c4 = 0; } else { col.c1 = (short)s.iv[0][j]; col.c2 = (short)s.iv[1][j]; col.c3 = (short)s.iv[2][j]; col.c4 = (short)s.iv[3][j]; } poCT->SetColorEntry(j, &col); } err = poBand->SetColorTable(poCT); delete poCT; return (err == CE_None); } SpatDataFrame grayColorTable() { SpatDataFrame coltab; std::vector col(256); std::iota(col.begin(), col.end(), 0); coltab.add_column(col, "red"); coltab.add_column(col, "green"); coltab.add_column(col, "blue"); std::fill(col.begin(), col.end(), 255); coltab.add_column(col, "alpha"); return coltab; } bool checkFormatRequirements(const std::string &driver, std::string &filename, std::string &msg) { if (driver == "SAGA") { std::string ext = getFileExt(filename); if (ext != ".sdat") { msg = "SAGA filenames must end on '.sdat'"; return false; } } return true; } void stat_options(int sstat, bool &compute_stats, bool &gdal_stats, bool &gdal_minmax, bool &gdal_approx) { compute_stats = true; gdal_stats = true; gdal_minmax = false; if (sstat == 1) { gdal_stats = false; } else if (sstat == 2) { gdal_stats = true; gdal_approx = true; } else if (sstat == 3) { gdal_stats = true; gdal_approx = false; } else if (sstat == 4) { gdal_minmax = true; gdal_approx = true; } else if (sstat == 5) { gdal_minmax = true; gdal_approx = false; } else { compute_stats = false; } } void removeVatJson(std::string filename) { std::vector exts = {".vat.dbf", ".vat.cpg", ".json"}; for (size_t i=0; iGetDriverByName(driver.c_str()); if(poDriver == NULL) { setError("invalid driver"); return (false); } char **papszMetadata; papszMetadata = poDriver->GetMetadata(); if (!CSLFetchBoolean( papszMetadata, GDAL_DCAP_RASTER, FALSE)) { setError(driver + " is not a raster format"); return false; } std::string datatype = opt.get_datatype(); bool writeRGB = (rgb && nlyr() == 3 && rgblyrs.size() == 3); if (writeRGB) { datatype = "INT1U"; } std::string errmsg; if (!checkFormatRequirements(driver, filename, errmsg)) { setError(errmsg); return false; } std::string appstr = "APPEND_SUBDATASET=YES"; bool append = std::find(opt.gdal_options.begin(), opt.gdal_options.end(), appstr) != opt.gdal_options.end(); if (append & (!CSLFetchBoolean( papszMetadata, GDAL_DMD_SUBDATASETS, FALSE))) { setError("cannot append datasets with this file format"); return false; } if (append & opt.get_overwrite()) { setError("cannot append and overwrite at the same time"); return false; } if (file_exists(filename) & (!opt.get_overwrite()) & (!append)) { setError("file exists. You can use 'overwrite=TRUE' to overwrite it"); return false; } removeVatJson(filename); // if (!can_write(filename, opt.get_overwrite(), errmsg)) { // setError(errmsg); // return(false); // } // what if append=true? std::string auxf = filename + ".aux.xml"; remove(auxf.c_str()); auxf = filename + ".aux.json"; remove(auxf.c_str()); std::vector hasCT = hasColors(); std::vector hasCats = hasCategories(); std::vector ct = getColors(); bool cat = hasCats[0]; bool rat = cat ? is_rat(source[0].cats[0].d) : false; if (rat) { if (hasCT[0]) { datatype = "INT1U"; } else { datatype = "INT4S"; } /* hasCats[0] = false; hasCT[0] = false; std::fill(hasCT.begin(), hasCT.end(), false); SpatCategories cats = source[0].cats[0]; SpatOptions sopt(opt); cats.d.write_dbf(filename, true, sopt); */ } else if (hasCT[0] || cat) { datatype = "INT1U"; } else if (datatype != "INT1U") { std::fill(hasCT.begin(), hasCT.end(), false); } if (opt.datatype_set) { if (datatype != opt.get_datatype()) { addWarning("changed datatype to " + datatype); } } GDALDataType gdt; if (!getGDALDataType(datatype, gdt)) { setError("invalid datatype"); return false; } source[0].datatype = datatype; int dsize = std::stoi(datatype.substr(3,1)); GIntBig diskNeeded = ncell() * nlyr() * dsize; std::string dname = dirname(filename); GIntBig diskAvailable = VSIGetDiskFreeSpace(dname.c_str()); if ((diskAvailable > -1) && (diskAvailable < diskNeeded)) { setError("insufficient disk space (perhaps from temporary files?)"); return(false); } stat_options(opt.get_statistics(), compute_stats, gdal_stats, gdal_minmax, gdal_approx); char **papszOptions = set_GDAL_options(driver, diskNeeded, writeRGB, opt.gdal_options); /* if (driver == "GTiff") { GDAL_tiff_options(diskNeeded > 4194304000, writeRGB, opt); } for (size_t i=0; i gopt = strsplit(opt.gdal_options[i], "="); if (gopt.size() == 2) { papszOptions = CSLSetNameValue( papszOptions, gopt[0].c_str(), gopt[1].c_str() ); } } if (writeRGB) { papszOptions = CSLSetNameValue( papszOptions, "PHOTOMETRIC", "RGB"); } */ //bool isncdf = ((driver == "netCDF" && opt.get_ncdfcopy())); GDALDataset *poDS; if (CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE)) { poDS = poDriver->Create(filename.c_str(), ncol(), nrow(), nlyr(), gdt, papszOptions); } else if (CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE)) { copy_driver = driver; gdal_options = opt.gdal_options; if (canProcessInMemory(opt)) { poDriver = GetGDALDriverManager()->GetDriverByName("MEM"); poDS = poDriver->Create("", ncol(), nrow(), nlyr(), gdt, papszOptions); } else { std::string f = tempFile(opt.get_tempdir(), opt.pid, ".tif"); copy_filename = f; poDriver = GetGDALDriverManager()->GetDriverByName("GTiff"); poDS = poDriver->Create(f.c_str(), ncol(), nrow(), nlyr(), gdt, papszOptions); } } else { setError("cannot write this format: "+ driver); CSLDestroy( papszOptions ); return false; } CSLDestroy( papszOptions ); if (poDS == NULL) { if (!filepath_exists(filename)) { setError("failed writing "+ driver + " file. Path does not exist:\n " + filename); } else { setError("failed writing "+ driver + " file"); } GDALClose( (GDALDatasetH) poDS ); return false; } #ifdef useRcpp if (opt.verbose) { double gb = 1073741824; char **filelist = poDS->GetFileList(); std::vector files; if (filelist != NULL) { for (size_t i=0; filelist[i] != NULL; i++) { files.push_back(filelist[i]); std::replace( files[i].begin(), files[i].end(), '\\', '/'); } } CSLDestroy( filelist ); for (size_t i=0; i 0) { Rcpp::Rcout<< "disk available: " << roundn(diskAvailable / gb, 1) << " GB" << std::endl; } Rcpp::Rcout<< "disk needed : " << roundn(diskNeeded / gb, 1) << " GB" << std::endl; } #endif if (opt.names.size() == nlyr()) { setNames(opt.names); } GDALRasterBand *poBand; std::vector nms = getNames(); double naflag=NAN; bool hasNAflag = opt.has_NAflag(naflag); if (writeRGB) nms = {"red", "green", "blue"}; for (size_t i=0; i < nlyr(); i++) { poBand = poDS->GetRasterBand(i+1); if ((i==0) && hasCT[i]) { if (!setCT(poBand, ct[i])) { addWarning("could not write the color table"); } } if (hasCats[i]) { if (is_rat(source[0].cats[i].d)) { if (!setRat(poBand, source[0].cats[i].d)) { addWarning("could not write attribute table"); } } else { SpatCategories lyrcats = getLayerCategories(i); if (lyrcats.d.ncol() == 2) { std::vector labs = getLabels(i); std::vector ind = lyrcats.d.as_long(0); if (!setBandCategories(poBand, ind, labs)) { addWarning("could not write categories"); } } } } /* if (isncdf) { std::string opt = "NETCDF_VARNAME"; char ** papszMetadata; papszMetadata = CSLSetNameValue( papszOptions, opt.c_str(), nms[i].c_str() ); poBand->SetMetadata(papszMetadata); } else { */ poBand->SetDescription(nms[i].c_str()); if ((i==0) || (driver != "GTiff")) { // to avoid "Setting nodata to nan on band 2, but band 1 has nodata at nan." if (hasNAflag) { poBand->SetNoDataValue(naflag); } else if (datatype == "INT4S") { poBand->SetNoDataValue(INT32_MIN); //-2147483648; } else if (datatype == "INT2S") { poBand->SetNoDataValue(INT16_MIN); } else if (datatype == "INT4U") { //double na = (double)UINT32_MAX; poBand->SetNoDataValue(UINT32_MAX); } else if (datatype == "INT2U") { //double na = (double)INT16_MAX * 2 - 1; poBand->SetNoDataValue(UINT16_MAX); } else if (datatype == "INT1U") { poBand->SetNoDataValue(255); } else { poBand->SetNoDataValue(NAN); } } if (writeRGB) { if (rgblyrs[i]==0) { poBand->SetColorInterpretation(GCI_RedBand); } else if (rgblyrs[i]==1) { poBand->SetColorInterpretation(GCI_GreenBand); } else if (rgblyrs[i]==2) { poBand->SetColorInterpretation(GCI_BlueBand); } } } std::vector rs = resolution(); SpatExtent extent = getExtent(); double adfGeoTransform[6] = { extent.xmin, rs[0], 0, extent.ymax, 0, -1 * rs[1] }; poDS->SetGeoTransform(adfGeoTransform); std::string crs = source[0].srs.wkt; OGRSpatialReference oSRS; OGRErr erro = oSRS.SetFromUserInput(&crs[0]); if (erro == 4) { setError("CRS failure"); GDALClose( (GDALDatasetH) poDS ); return false ; } char *pszSRS_WKT = NULL; oSRS.exportToWkt(&pszSRS_WKT); poDS->SetProjection(pszSRS_WKT); CPLFree(pszSRS_WKT); // destroySRS(oSRS) ? source[0].resize(nlyr()); source[0].nlyrfile = nlyr(); source[0].datatype = datatype; for (size_t i =0; i::max(); source[0].range_max[i] = NAN; //std::numeric_limits::lowest(); } source[0].driver = "gdal" ; source[0].filename = filename; source[0].memory = false; write_aux_json(filename); /* if (append) { GDALClose( (GDALDatasetH) poDS ); std::vector ops; poDS = openGDAL(filename, GDAL_OF_RASTER | GDAL_OF_UPDATE, ops); std::vector subds; char **metadata = poDS->GetMetadata("SUBDATASETS"); if (metadata != NULL) { for (size_t i=0; metadata[i] != NULL; i++) { subds.push_back(metadata[i]); } std::vector> s = parse_metadata_sds(subds); GDALClose( (GDALDatasetH) poDS ); filename = s[0].back(); poDS = openGDAL(filename, GDAL_OF_RASTER | GDAL_OF_UPDATE, ops); } } */ source[0].gdalconnection = poDS; return true; } /* void min_max_na(std::vector &vals, const double &na, const double &mn, const double &mx) { for (double &v : vals) { v = std::isnan(v) ? na : (v < mn ? na : (v > mx ? na : v)); } } */ template void tmp_min_max_na(std::vector &out, const std::vector &v, const double &na, const double &mn, const double &mx) { size_t n = v.size(); out.reserve(n); for (size_t i=0; i mx ? na : v[i]))); } } bool SpatRaster::writeValuesGDAL(std::vector &vals, size_t startrow, size_t nrows, size_t startcol, size_t ncols){ CPLErr err = CE_None; double vmin, vmax; size_t nc = nrows * ncols; size_t nl = nlyr(); std::string datatype = source[0].datatype; if ((compute_stats) && (!gdal_stats)) { for (size_t i=0; i < nl; i++) { size_t start = nc * i; if (datatype == "INT4S") { minmaxlim(vals.begin()+start, vals.begin()+start+nc, vmin, vmax, (double)INT32_MIN, (double)INT32_MAX); } else if (datatype == "INT2S") { minmaxlim(vals.begin()+start, vals.begin()+start+nc, vmin, vmax, (double)INT16_MIN, (double)INT16_MAX); } else if (datatype == "INT4U") { minmaxlim(vals.begin()+start, vals.begin()+start+nc, vmin, vmax, 0.0, (double)UINT32_MAX); } else if (datatype == "INT2U") { minmaxlim(vals.begin()+start, vals.begin()+start+nc, vmin, vmax, 0.0, (double)UINT16_MAX); } else if (datatype == "INT1U") { minmaxlim(vals.begin()+start, vals.begin()+start+nc, vmin, vmax, 0.0, 255.0); } else { minmax(vals.begin()+start, vals.begin()+start+nc, vmin, vmax); } if (!std::isnan(vmin)) { if (std::isnan(source[0].range_min[i])) { source[0].range_min[i] = vmin; source[0].range_max[i] = vmax; } else { source[0].range_min[i] = std::min(source[0].range_min[i], vmin); source[0].range_max[i] = std::max(source[0].range_max[i], vmax); } } } } if ((datatype == "FLT8S") || (datatype == "FLT4S")) { err = source[0].gdalconnection->RasterIO(GF_Write, startcol, startrow, ncols, nrows, &vals[0], ncols, nrows, GDT_Float64, nl, NULL, 0, 0, 0, NULL ); } else { int hasNA=0; double na = source[0].gdalconnection->GetRasterBand(1)->GetNoDataValue(&hasNA); if (!hasNA) { na = NAN; } if (datatype == "INT4S") { //min_max_na(vals, na, (double)INT32_MIN, (double)INT32_MAX); //std::vector vv(vals.begin(), vals.end()); std::vector vv; tmp_min_max_na(vv, vals, na, (double)INT32_MIN, (double)INT32_MAX); err = source[0].gdalconnection->RasterIO(GF_Write, startcol, startrow, ncols, nrows, &vv[0], ncols, nrows, GDT_Int32, nl, NULL, 0, 0, 0, NULL ); } else if (datatype == "INT2S") { //min_max_na(vals, na, (double)INT16_MIN, (double)INT16_MAX); //std::vector vv(vals.begin(), vals.end()); std::vector vv; tmp_min_max_na(vv, vals, na, (double)INT16_MIN, (double)INT16_MAX); err = source[0].gdalconnection->RasterIO(GF_Write, startcol, startrow, ncols, nrows, &vv[0], ncols, nrows, GDT_Int16, nl, NULL, 0, 0, 0, NULL ); } else if (datatype == "INT4U") { //min_max_na(vals, na, 0, (double)INT32_MAX * 2 - 1); //std::vector vv(vals.begin(), vals.end()); std::vector vv; tmp_min_max_na(vv, vals, na, 0, (double)UINT32_MAX); err = source[0].gdalconnection->RasterIO(GF_Write, startcol, startrow, ncols, nrows, &vv[0], ncols, nrows, GDT_UInt32, nl, NULL, 0, 0, 0, NULL ); } else if (datatype == "INT2U") { //min_max_na(vals, na, 0, (double)INT16_MAX * 2 - 1); //std::vector vv(vals.begin(), vals.end()); std::vector vv; tmp_min_max_na(vv, vals, na, 0, (double)UINT16_MAX); err = source[0].gdalconnection->RasterIO(GF_Write, startcol, startrow, ncols, nrows, &vv[0], ncols, nrows, GDT_UInt16, nl, NULL, 0, 0, 0, NULL ); } else if (datatype == "INT1U") { //min_max_na(vals, na, 0, 255); //std::vector vv(vals.begin(), vals.end()); std::vector vv; tmp_min_max_na(vv, vals, na, 0, 255); err = source[0].gdalconnection->RasterIO(GF_Write, startcol, startrow, ncols, nrows, &vv[0], ncols, nrows, GDT_Byte, nl, NULL, 0, 0, 0, NULL ); } else { setError("bad datatype"); GDALClose( source[0].gdalconnection ); return false; } } if (err != CE_None ) { setError("cannot write values (err: " + std::to_string(err) +")"); GDALClose( source[0].gdalconnection ); return false; } return true; } bool SpatRaster::writeStopGDAL() { GDALRasterBand *poBand; source[0].hasRange.resize(nlyr()); std::string datatype = source[0].datatype; for (size_t i=0; i < nlyr(); i++) { poBand = source[0].gdalconnection->GetRasterBand(i+1); if (compute_stats) { if (gdal_stats) { double mn, mx, av=-9999, sd=-9999; //int approx = gdal_approx; if (gdal_minmax) { double adfMinMax[2]; poBand->ComputeRasterMinMax(gdal_approx, adfMinMax); mn = adfMinMax[0]; mx = adfMinMax[1]; } else { poBand->ComputeStatistics(gdal_approx, &mn, &mx, &av, &sd, NULL, NULL); } poBand->SetStatistics(mn, mx, av, sd); } else { if (datatype.substr(0,3) == "INT") { source[0].range_min[i] = trunc(source[0].range_min[i]); source[0].range_max[i] = trunc(source[0].range_max[i]); } poBand->SetStatistics(source[0].range_min[i], source[0].range_max[i], -9999., -9999.); } source[0].hasRange[i] = true; } else { source[0].hasRange[i] = false; } } if (copy_driver != "") { GDALDataset *newDS; GDALDriver *poDriver; char **papszOptions = set_GDAL_options(copy_driver, 0.0, false, gdal_options); poDriver = GetGDALDriverManager()->GetDriverByName(copy_driver.c_str()); if (copy_filename == "") { newDS = poDriver->CreateCopy(source[0].filename.c_str(), source[0].gdalconnection, FALSE, papszOptions, NULL, NULL); if( newDS == NULL ) { setError("mem copy create failed for "+ copy_driver); copy_driver = ""; GDALClose( (GDALDatasetH) newDS ); GDALClose( (GDALDatasetH) source[0].gdalconnection ); return false; } copy_driver = ""; GDALClose( (GDALDatasetH) newDS ); GDALClose( (GDALDatasetH) source[0].gdalconnection ); } else { GDALClose( (GDALDatasetH) source[0].gdalconnection ); GDALDataset *oldDS = openGDAL(copy_filename.c_str(), GDAL_OF_RASTER | GDAL_OF_READONLY, source[0].open_ops); if( oldDS == NULL ) { setError("file copy create failed for "+ copy_driver); copy_driver = ""; copy_filename = ""; GDALClose( (GDALDatasetH) oldDS ); return false; } newDS = poDriver->CreateCopy(source[0].filename.c_str(), oldDS, FALSE, papszOptions, NULL, NULL); if( newDS == NULL ) { setError("copy create failed for "+ copy_driver); copy_driver = ""; copy_filename = ""; GDALClose( (GDALDatasetH) oldDS ); GDALClose( (GDALDatasetH) newDS ); return false; } copy_driver = ""; copy_filename = ""; GDALClose( (GDALDatasetH) oldDS ); GDALClose( (GDALDatasetH) newDS ); } CSLDestroy(papszOptions); } else { GDALClose( (GDALDatasetH) source[0].gdalconnection ); } source[0].hasValues = true; return true; } bool SpatRaster::fillValuesGDAL(double fillvalue) { CPLErr err = CE_None; GDALRasterBand *poBand; for (size_t i=0; i < nlyr(); i++) { poBand = source[0].gdalconnection->GetRasterBand(i+1); err = poBand->Fill(fillvalue); } if (err != CE_None ) { setError("cannot fill values"); return false; } return true; } terra/src/extract.cpp0000644000175000017500000010102414201035750014461 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include #include "spatRasterMultiple.h" #include "distance.h" #include "vecmath.h" double rowColToCell(unsigned ncols, unsigned row, unsigned col) { return row * ncols + col; } std::vector SpatRaster::fourCellsFromXY(const std::vector &x, const std::vector &y) { size_t n = x.size(); SpatExtent e = getExtent(); std::vector out; out.reserve(4*n); double xmin = e.xmin; double xmax = e.xmax; double xr = xres(); double ymin = e.ymin; double ymax = e.ymax; double yr = yres(); double nc = ncol(); int_64 mxr = nrow()-1; int_64 mxc = ncol()-1; int_64 r1, r2, c1, c2; std::vector bad = {NAN, NAN, NAN, NAN}; for (size_t i = 0; i < n; i++) { if (y[i] < ymin || y[i] > ymax || x[i] < xmin || x[i] > xmax) { out.insert(out.end(), bad.begin(), bad.end()); continue; } if (y[i] == ymin) { r1 = mxr; r2 = mxr; } else { double p = (ymax - y[i]) / yr; r1 = trunc(p); if ((p - r1) > 0.5) { r2 = r1 == mxr ? mxr : r1 + 1; } else { r2 = r1; r1 = r1 == 0 ? 0 : r1 - 1; } } if (x[i] == xmax) { c1 = mxc; c2 = mxc; } else { double p = (x[i] - xmin) / xr; c1 = trunc(p); if ((p - c1) > 0.5) { c2 = c1 == mxc ? mxc : c1 + 1; } else { c2 = c1; c1 = c2 == 0 ? 0 : c2 - 1; } } out.push_back(r1 * nc + c1); out.push_back(r1 * nc + c2); out.push_back(r2 * nc + c1); out.push_back(r2 * nc + c2); } return out; } /* double linearInt(const double& d, const double& x, const double& x1, const double& x2, const double& v1, const double& v2) { double result = (v2 * (x - x1) + v1 * (x2 - x)) / d; return result; } */ /* ok but cannot handle NA double bilinearInt(const double& x, const double& y, const double& x1, const double& x2, const double& y1, const double& y2, const double& v11, const double& v21, const double& v12, const double& v22) { double d = x2-x1; double h1 = linearInt(d, x, x1, x2, v11, v21); double h2 = linearInt(d, x, x1, x2, v12, v22); d = y2-y1; double v = linearInt(d, y, y1, y2, h1, h2); return v; } */ /* double bilinearIntold(const double& x, const double& y, const double& x1, const double& x2, const double& y1, const double& y2, const double& v11, const double& v21, const double& v12, const double& v22) { double d = x2-x1; double h1=NAN; double h2=NAN; if (!std::isnan(v11) && !std::isnan(v21)) { h1 = linearInt(d, x, x1, x2, v11, v21); } else if (!std::isnan(v11)) { h1 = v11; } else if (!std::isnan(v21)) { h1 = v21; } if (!std::isnan(v12) && !std::isnan(v22)) { h2 = linearInt(d, x, x1, x2, v12, v22); } else if (!std::isnan(v12)) { h2 = v12; } else if (!std::isnan(v22)) { h2 = v22; } if (!std::isnan(h1) && !std::isnan(h2)) { d = y2-y1; double v = linearInt(d, y, y1, y2, h1, h2); return v; } else if (!std::isnan(h1)) { return h1; } else if (!std::isnan(h2)) { return h2; } return NAN; } */ std::vector bilinearInt(const double& x, const double& y, const double& x1, const double& x2, const double& y1, const double& y2, double& v11, double& v12, double& v21, double& v22, bool weights) { bool n1 = std::isnan(v11); bool n2 = std::isnan(v12); bool n3 = std::isnan(v21); bool n4 = std::isnan(v22); if (std::isnan(x) || std::isnan(y) || (n1 && n2 && n3 && n4)) { if (weights) { std::vector out(4, NAN); return out; } std::vector out(1, NAN); return out; } double dx = (x2 - x1); bool intx = dx > 0; double dy = (y1 - y2); bool inty = dy > 0; double w11, w12, w21, w22; if (weights) { v11 = 1; v12 = 1; v21 = 1; v22 = 1; } if (intx & inty) { double d = dx * dy; if (!(n1 || n2)) { w11 = v11 * ((x2 - x) * (y - y2)) / d; w12 = v12 * ((x - x1) * (y - y2)) / d; } else { w11 = n1 ? 0.0 : 0.5 * v11; w12 = n2 ? 0.0 : 0.5 * v12; } if (!(n3 || n4)) { w21 = v21 * ((x2 - x) * (y1 - y)) / d; w22 = v22 * ((x - x1) * (y1 - y)) / d; } else { w21 = n3 ? 0.0 : 0.5 * v21; w22 = n4 ? 0.0 : 0.5 * v22; } } else if (intx) { if (!(n1 || n2)) { w11 = v11 * (x2 - x) / dx; w12 = v12 * (x - x1) / dx; } else { w11 = n1 ? 0.0 : v11; w12 = n2 ? 0.0 : v12; } w21 = 0; w22 = 0; } else if (inty) { if (!(n1 || n3)) { w11 = v11 * (y - y2) / dy; w21 = v21 * (y1 - y) / dy; } else { w11 = n1 ? 0.0 : v11; w21 = n3 ? 0.0 : v21; } w12 = 0; w22 = 0; } else { w11 = v11; w21 = 0; w12 = 0; w22 = 0; } if (weights) { std::vector out = { w11, w12, w21, w22 }; return out; } std::vector out = { w11 + w12 + w21 + w22 }; return out; } /* double distInt(double d, double pd1, double pd2, double v1, double v2) { double result = (v2 * pd1 + v1 * pd2) / d; return result; } double bilinear_geo(double x, double y, double x1, double x2, double y1, double y2, double halfyres, std::vector vv) { double a = 6378137.0; double f = 1/298.257223563; double hy = y1 - halfyres; double d = distance_lonlat(x1, hy, x2, hy, a, f); std::vector dist(4); double pd1 = distance_lonlat(x, hy, x1, hy, a, f); double pd2 = distance_lonlat(x, hy, x2, hy, a, f); double h1 = distInt(d, pd1, pd2, vv[0], vv[1]); double h2 = distInt(d, pd1, pd2, vv[2], vv[3]); d = y2 - y1; double v = linearInt(d, y, y1, y2, h1, h2); return v; } */ std::vector> SpatRaster::bilinearValues(const std::vector &x, const std::vector &y) { std::vector four = fourCellsFromXY(x, y); std::vector> xy = xyFromCell(four); std::vector> v = extractCell(four); size_t n = x.size(); // double halfyres = yres()/2; std::vector> res(nlyr(), std::vector(n)); /* if (lonlat) { for (size_t i=0; i vv(v[j].begin()+ii, v[j].begin()+ii+4); if (i==0) { std::cout << x[i] << " "<< y[i] << "\n"; std::cout << xy[0][ii] << " " << xy[0][ii+1] << " " << xy[1][ii] << " " << xy[1][ii+3] << "\n"; std::cout << v[j][ii] << " " << v[j][ii+1] << " " << v[j][ii+2] << " " << v[j][ii+3] << "\n"; } res[j][i] = bilinear_geo(x[i], y[i], xy[0][ii], xy[0][ii+1], xy[1][ii], xy[1][ii+3], halfyres, vv); } } } else { */ for (size_t i=0; i value = bilinearInt(x[i], y[i], xy[0][ii], xy[0][ii+1], xy[1][ii], xy[1][ii+3], v[j][ii], v[j][ii+1], v[j][ii+2], v[j][ii+3], false); res[j][i] = value[0]; } } // } return res; } std::vector SpatRaster::bilinearCells(const std::vector &x, const std::vector &y) { std::vector four = fourCellsFromXY(x, y); std::vector> xy = xyFromCell(four); std::vector> v = extractCell(four); size_t n = x.size(); std::vector res; std::vector w; for (size_t i=0; i w = bilinearInt(x[i], y[i], xy[0][ii], xy[0][ii+1], xy[1][ii], xy[1][ii+3], v[j][ii], v[j][ii+1], v[j][ii+2], v[j][ii+3], true); res.insert(res.end(), four.begin()+ii, four.begin()+ii+4); res.insert(res.end(), w.begin(), w.end()); } return res; } double bilinear(const std::vector &v, const std::vector &e, const double &dxdy, const double &x, const double &y) { // values // v[0] v[1] // v[2] v[3] // coordinates // e[3] (ymax) // (xmin)e[0] e[1] (xmax) // e[2] (ymin) double dx1 = x - e[0]; double dx2 = e[1] - x; double dy1 = y - e[2]; double dy2 = e[3] - y; return (v[2] * dx2 * dy2 + v[3] * dx1 * dy2 + v[0] * dx2 * dy1 + v[1] * dx1 * dy1) / dxdy; } std::vector SpatRaster::line_cells(SpatGeom& g) { unsigned nrows = nrow(); unsigned ncols = ncol(); SpatExtent extent = getExtent(); double xmin = extent.xmin; double ymax = extent.ymax; double rx = xres(); double ry = yres(); std::vector out; unsigned np = g.size(); for (size_t prt=0; prt nrows || maxrow < 0) { return(out); } size_t startrow = minrow < 0 ? 0 : minrow; size_t endrow = maxrow >= nrows ? (nrows-1) : maxrow; unsigned n = p.x.size(); out.reserve(2*(startrow-endrow+1)); for (size_t row=startrow; row= y)) || ((p.y[j] < y) && (p.y[i] >= y))) { double col = ((p.x[i] - xmin + (y-p.y[i])/(p.y[j]-p.y[i]) * (p.x[j]-p.x[i])) + 0.5 * rx ) / rx; if ((col >= 0) & (col < ncols)) { out.push_back(rowcell + col); } } } } } return(out); } std::vector SpatRaster::polygon_cells(SpatGeom& g) { // does not deal with holes yet. unsigned nrows = nrow(); unsigned ncols = ncol(); SpatExtent extent = getExtent(); double xmin = extent.xmin; double ymax = extent.ymax; double rx = xres(); double ry = yres(); std::vector out; unsigned np = g.size(); for (size_t prt=0; prt nrows || maxrow < 0) { return(out); } size_t startrow = minrow < 0 ? 0 : minrow; size_t endrow = maxrow >= nrows ? (nrows-1) : maxrow; unsigned n = p.x.size(); out.reserve(5*(startrow-endrow+1)); std::vector nCol(n); for (size_t row=0; row= y)) || ((p.y[j] < y) && (p.y[i] >= y))) { // nCol[nodes++]=(int) (((pX[i] - xmin + (y-pY[i])/(pY[j]-pY[i]) * (pX[j]-pX[i])) + 0.5 * rx ) / rx); double nds = ((p.x[i] - xmin + (y-p.y[i])/(p.y[j]-p.y[i]) * (p.x[j]-p.x[i])) + 0.5 * rx ) / rx; nds = nds < 0 ? 0 : nds; nds = nds > ncols ? ncols : nds; nCol[nodes] = (unsigned) nds; nodes++; } j = i; } // now remove the holes? std::sort(nCol.begin(), nCol.begin()+nodes); unsigned rowcell = ncols * row; // fill cells between node pairs. for (size_t i=0; i < nodes; i+=2) { if (nCol[i+1] > 0 && nCol[i] < ncols) { // surely should be >= 0? for (size_t col = nCol[i]; col < nCol[i+1]; col++) { out.push_back(col + rowcell); } } } } } return(out); } /* idw bool lonlat = could_be_lonlat(); //bool globalLonLat = is_global_lonlat(); //size_t n = x.size(); if (method == "idw") { std::function(std::vector&,std::vector&,double,double)> distFun; // std::vector distance_plane(std::vector &x1, std::vector &y1, std::vector &x2, std::vector &y2); if (lonlat) { distFun = distance_lonlat_vd; } else { distFun = distance_plane_vd; } */ /* cxy = xyFromCell(cells); d = distFun(cxy[0], cxy[1], x[i], y[i]); v = extractCell(cells); double a=0, b=0; for (size_t j=0; j<4; j++) { a += v[j] * d[j]; b += d[j]; } out[i] = a / b; */ // > std::vector> SpatRaster::extractXY(const std::vector &x, const std::vector &y, const std::string &method, const bool &cells) { unsigned nl = nlyr(); unsigned np = x.size(); if (!hasValues()) { std::vector> out(nl+cells, std::vector(np, NAN)); return out; } std::vector> out; if (method == "bilinear") { out = bilinearValues(x, y); if (cells) { std::vector cell = cellFromXY(x, y); out.push_back(cell); } } else { std::vector cell = cellFromXY(x, y); out = extractCell(cell); if (cells) { out.push_back(cell); } } return out; } std::vector SpatRaster::extractXYFlat(const std::vector &x, const std::vector &y, const std::string & method, const bool &cells) { // > std::vector> e = extractXY(x, y, method, cells); std::vector out = e[0]; for (size_t i=1; i std::vector flatten(const std::vector>& v) { std::size_t total_size = 0; for (const auto& sub : v) total_size += sub.size(); std::vector result; result.reserve(total_size); for (const auto& sub : v) result.insert(result.end(), sub.begin(), sub.end()); return result; } */ /* std::vector SpatRaster::extractXYFlat(const std::vector &x, const std::vector &y, const std::string & method, const bool &cells) { unsigned nl = nlyr(); unsigned np = x.size(); if (!hasValues()) { std::vector out(nl * np, NAN); return out; } std::vector out; if (method == "bilinear") { std::vector> bil = bilinearValues(x, y); if (cells) { std::vector cell = cellFromXY(x, y); bil.push_back(cell); } out = flatten(bil); } else { std::vector cell = cellFromXY(x, y); if (cells) { std::vector> xout; xout = extractCell(cell); xout.push_back(cell); out = flatten(xout); } else { out = extractCellFlat(cell); } } return out; } */ // >> std::vector>> SpatRaster::extractVector(SpatVector v, bool touches, std::string method, bool cells, bool xy, bool weights, bool exact, SpatOptions &opt) { std::string gtype = v.type(); if (gtype != "polygons") weights = false; if (exact) weights = false; unsigned nl = nlyr(); unsigned ng = v.size(); std::vector>> out(ng, std::vector>(nl + cells + 2*xy + (weights || exact))); if (!hasValues()) { setError("raster has no value"); return out; } /* #if GDAL_VERSION_MAJOR < 3 if (weights) { setError("extract with weights not supported for your GDAL version"); return out; } #endif */ std::vector> srcout; if (gtype == "points") { if (method != "bilinear") method = "simple"; SpatDataFrame vd = v.getGeometryDF(); if (vd.nrow() == ng) { // single point geometry std::vector x = vd.getD(0); std::vector y = vd.getD(1); srcout = extractXY(x, y, method, cells); for (size_t i=0; i x = vd.getD(0); std::vector y = vd.getD(1); //srcout = extractXY(x, y, method, cells); // Rcpp::Rcout << srcout.size() << " " << srcout[0].size() << std::endl; /* for (size_t j=0; j feats(1, 1) ; for (size_t i=0; i cell, wgt; if (weights) { rasterizeCellsWeights(cell, wgt, p, opt); } else if (exact) { rasterizeCellsExact(cell, wgt, p, opt); } else { cell = rasterizeCells(p, touches, opt); } srcout = extractCell(cell); for (size_t j=0; j> crds = xyFromCell(cell); out[i][nl+cells] = crds[0]; out[i][nl+cells+1] = crds[1]; } if (weights || exact) { out[i][nl + cells + 2*xy] = wgt; } } } return out; } std::vector SpatRaster::extractVectorFlat(SpatVector v, bool touches, std::string method, bool cells, bool xy, bool weights, bool exact, SpatOptions &opt) { std::vector flat; std::string gtype = v.type(); if (gtype != "polygons") weights = false; unsigned nl = nlyr(); unsigned ng = v.size(); if (!hasValues()) { setError("raster has no value"); return flat; } /* #if GDAL_VERSION_MAJOR < 3 if (weights) { setError("extract with weights not supported for your GDAL version"); return out; } #endif */ std::vector>> out; if (gtype != "points") { out.resize(ng, std::vector>(nl + cells + 2*xy + (weights||exact))); } std::vector> srcout; if (gtype == "points") { if (method != "bilinear") method = "simple"; SpatDataFrame vd = v.getGeometryDF(); //if (vd.nrow() == ng) { // single point geometry std::vector x = vd.getD(0); std::vector y = vd.getD(1); if (!cells & !xy & !weights) { return( extractXYFlat(x, y, method, cells)); } else { srcout = extractXY(x, y, method, cells); nl += cells; flat.reserve(ng * nl); for (size_t i=0; i x = vd.getD(0); std::vector y = vd.getD(1); if (!cells & !xy & !weights) { return( extractXYFlat(x, y, method, cells)); } for (size_t i=0; i x = vd.getD(0); std::vector y = vd.getD(1); srcout = extractXY(x, y, method, cells); Rcpp::Rcout << srcout.size() << " " << srcout[0].size(); out.push_back(srcout); if (cells) { out[i][nl] = srcout[nl]; } if (xy) { out[i][nl+cells] = x; out[i][nl+cells+1] = y; } } } */ } else { SpatRaster r = geometry(1); //std::vector feats(1, 1) ; for (size_t i=0; i cell, wgt; if (weights) { rasterizeCellsWeights(cell, wgt, p, opt); } else if (exact) { rasterizeCellsExact(cell, wgt, p, opt); } else { cell = rasterizeCells(p, touches, opt); } srcout = extractCell(cell); for (size_t j=0; j> crds = xyFromCell(cell); out[i][nl+cells] = crds[0]; out[i][nl+cells+1] = crds[1]; } if (weights || exact) { out[i][nl + cells + 2*xy] = wgt; } } } size_t fsize = 0; for (size_t i=0; i> SpatRaster::extractCell(std::vector &cell) { std::vector wcell; std::vector> rc, wrc; rc = rowColFromCell(cell); size_t n = cell.size(); std::vector> out(nlyr(), std::vector(n, NAN)); if (!hasValues()) return out; unsigned ns = nsrc(); unsigned lyr = 0; size_t nc; for (size_t src=0; src= 0 && wcell[k] < nc) { out[lyr][k] = source[src].values[j + wcell[k]]; } } } else { for (size_t k=0; k= 0 && cell[k] < nc) { out[lyr][k] = source[src].values[j + cell[k]]; } } } lyr++; } } else { std::vector> srcout; //if (source[0].driver == "raster") { // srcout = readCellsBinary(src, cell); //} else { #ifdef useGDAL if (win) { srcout = readRowColGDAL(src, wrc[0], wrc[1]); } else { srcout = readRowColGDAL(src, rc[0], rc[1]); } #endif if (hasError()) return out; //} for (size_t i=0; i SpatRaster::extractCellFlat(std::vector &cell) { std::vector wcell; std::vector> rc, wrc; rc = rowColFromCell(cell); size_t n = cell.size(); std::vector out(nlyr() * n, NAN); unsigned ns = nsrc(); unsigned lyr = 0; size_t nc; size_t off = 0; for (size_t src=0; src= 0 && wcell[k] < nc) { out[off2+k] = source[src].values[j + wcell[k]] ; } } } else { for (size_t k=0; k= 0 && cell[k] < nc) { out[off2+k] = source[src].values[j + cell[k]]; } } } lyr++; } } else { //if (source[0].driver == "raster") { // srcout = readCellsBinary(src, cell); //} else { #ifdef useGDAL std::vector g; if (win) { g = readRowColGDALFlat(src, wrc[0], wrc[1]); } else { g = readRowColGDALFlat(src, rc[0], rc[1]); } for (size_t i=0; i SpatRaster::vectCells(SpatVector v, bool touches, std::string method, bool weights, bool exact, SpatOptions &opt) { std::string gtype = v.type(); if (gtype != "polygons") weights = false; std::vector out, cells, wghts; if (gtype == "points") { SpatDataFrame vd = v.getGeometryDF(); std::vector id = vd.getI(0); if (method == "bilinear") { return bilinearCells(vd.getD(0), vd.getD(1)); } else { return cellFromXY(vd.getD(0), vd.getD(1)); //cells = cellFromXY(vd.getD(0), vd.getD(1)); //out.insert(out.end(), id.begin(), id.end()); //out.insert(out.end(), cells.begin(), cells.end()); } } else { unsigned ng = v.size(); SpatRaster r = geometry(1); std::vector feats(1, 1) ; for (size_t i=0; i cnr, wght; rasterizeCellsWeights(cnr, wght, p, opt); std::vector id(cnr.size(), i); out.insert(out.end(), id.begin(), id.end()); cells.insert(cells.end(), cnr.begin(), cnr.end()); wghts.insert(wghts.end(), wght.begin(), wght.end()); } else if (exact) { std::vector cnr, wght; rasterizeCellsExact(cnr, wght, p, opt); std::vector id(cnr.size(), i); out.insert(out.end(), id.begin(), id.end()); cells.insert(cells.end(), cnr.begin(), cnr.end()); wghts.insert(wghts.end(), wght.begin(), wght.end()); } else { std::vector geomc = rasterizeCells(p, touches, opt); std::vector id(geomc.size(), i); out.insert(out.end(), id.begin(), id.end()); cells.insert(cells.end(), geomc.begin(), geomc.end()); } } if (weights || exact) { out.insert(out.end(), cells.begin(), cells.end()); out.insert(out.end(), wghts.begin(), wghts.end()); } else { out.insert(out.end(), cells.begin(), cells.end()); } } return out; } std::vector SpatRaster::extCells(SpatExtent ext) { std::vector out; ext = align(ext, "near"); ext = ext.intersect(getExtent()); if (!ext.valid()) { return(out); } double resx = xres() / 2; double resy = yres() / 2; std::vector e = ext.asVector(); e[0] += resx; e[1] -= resx; e[2] += resy; e[3] -= resy; std::vector ex = {e[0], e[1]}; std::vector ey = {e[3], e[2]}; std::vector r = rowFromY(ey); std::vector c = colFromX(ex); int_64 nc = ncol(); out.reserve((r[1]-r[0]) * (c[1]-c[0])); for (int_64 i=r[0]; i <= r[1]; i++) { for (int_64 j=c[0]; j <= c[1]; j++) { out.push_back(i*nc+j); } } return out; } std::vector>> SpatRasterStack::extractXY(std::vector &x, std::vector &y, std::string method) { unsigned ns = nsds(); std::vector>> out(ns); bool cells = false; for (size_t i=0; i>> SpatRasterStack::extractCell(std::vector &cell) { unsigned ns = nsds(); std::vector>> out(ns); for (size_t i=0; i>>> SpatRasterStack::extractVector(SpatVector v, bool touches, std::string method, SpatOptions &opt) { unsigned ns = nsds(); std::vector>>> out(ns); for (size_t i=0; i f = {2,2}; SpatRaster gd = g.disaggregate(f, opt); double dyrs = gd.yres(); double dxrs = gd.xres(); std::vector d, cells(4); std::vector > cxy; std::vector rc(4); unsigned nr = nrow(); unsigned nc = ncol(); unsigned mnr = nr-1; unsigned mnc = nc-1; // needs row-wise adjustment for lonlat double dxdy = xres() * yres(); for (size_t i=0; i mnr)) { continue; } double row2 = (rq == 0) ? row1-1 : row1+1; row2 = row2 < 0 ? row1+1 : row2==nr ? row1-1 : row2; double col2; if (globalLonLat) { if ((col1 < -1) | (col1 > nc)) { continue; } col1 = col1 < 0 ? mnc : col1 > mnc ? 0 : col1; col2 = (cq == 0) ? col1-1 : col1 + 1; col2 = col2 < 0 ? mnc : col2 > mnc ? 0 : col2; } else { if ((col1 < 0) | (col1 > mnc)) { continue; } col2 = (cq == 0) ? col1-1 : col1 + 1; col2 = col2 < 0 ? col1+1 : col2 == nc ? col1-1 : col2; } cells[0] = nc * row1 + col1; cells[1] = nc * row1 + col2; cells[2] = nc * row2 + col1; cells[3] = nc * row2 + col2; std::sort(cells.begin(), cells.end()); std::vector> xy = xyFromCell(cells); std::vector> v = extractCell(cells); std::vector e = {xy[0][0], xy[0][1], xy[1][2], xy[1][0]}; for (size_t j=0; j SpatRaster::extractCell(std::vector &cell) { unsigned n = cell.size(); unsigned nc = ncell(); std::vector out; if (!hasValues()) { out = std::vector(n * nlyr(), NAN) return out; } unsigned ns = nsrc(); for (size_t src=0; src srcout; if (source[src].memory) { srcout = std::vector(n * slyrs, NAN) std::vector off1(slyrs); std::vector off2(slyrs); for (size_t i=0; i= 0 && cell[i] < nc) { for (size_t j=0; j> rc = rowColFromCell(cell); srcout = readRowColGDAL(src, rc[0], rc[1]); #endif if (hasError()) return out; //} } out.insert(out.end(), srcout.begin(), srcout.end()); } return out; } */ terra/src/date.h0000644000175000017500000001370214201035750013376 0ustar nileshnilesh// Copyright (c) 2018-2020 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #ifndef SPATDATE_GUARD #define SPATDATE_GUARD #include //#include //#include class SpatDate { public: long long v; SpatDate() {v = 0;}; SpatDate(const int& year, const int& month, const int& day); SpatDate(int doy, int year); SpatDate(const long& d) { v = d; }; // SpatDate(const std::string& s); virtual ~SpatDate(){} std::vector ymd(); int doy(); bool is_leap_year(); SpatDate operator ++(); // prefix SpatDate operator ++(int); // postfix SpatDate operator --(); // prefix SpatDate operator --(int); // postfix void operator = (const SpatDate&); }; SpatDate operator + (SpatDate&, int); SpatDate operator + (int, SpatDate&); SpatDate operator - (SpatDate&, int); int operator - (SpatDate&, SpatDate&); bool operator == (const SpatDate&, const SpatDate&); bool operator != (const SpatDate&, const SpatDate&); bool operator < (const SpatDate&, const SpatDate&); bool operator > (const SpatDate&, const SpatDate&); bool operator <= (const SpatDate&, const SpatDate&); bool operator >= (const SpatDate&, const SpatDate&); bool isleapyear(const int& year) { return (year % 4 == 0) && ((year % 400 == 0) || (year % 100 != 0 )); } std::vector month_days(int year) { if (isleapyear(year)) { std::vector md {31,29,31,30,31,30,31,31,30,31,30,31}; return md; } else { std::vector md {31,28,31,30,31,30,31,31,30,31,30,31}; return md; } } std::vector SpatDate::ymd() { int year, month, day; long x = v; if (x >= 0) { long days = 0; year = 1969; while (days <= x) { year++; days += (365 + isleapyear(year)); } x = x - days + (365 + isleapyear(year)); std::vector mdays = month_days(year); days = -1; month = -1; while (days < x) { month++; days += mdays[month]; } day = x - days + mdays[month]; month++; } else { // (x < 0) long days = 0; year = 1970; while (days > x) { year--; days -= (365 + isleapyear(year)); } x = x - (days + (365 + isleapyear(year))); x = abs(x); std::vector mdays = month_days(year); days = 0; month = 12; while (days < x) { month--; days += mdays[month]; } day = days - x +1; month++; } std::vector result {year, month, day}; return result; } int date_from_ymd(std::vector ymd) { int year = 1970; long day = -1; if (ymd[0] > 1970) { for (int i=0; i<(ymd[0]-1970); i++) { day += 365 + isleapyear(year); year++; } std::vector mdays = month_days(year); for (int i=0; i<(ymd[1]-1); i++) { day += mdays[i]; } day += ymd[2]; } else { day = -1; for (int i=0; i<(1970-ymd[0]); i++) { day -= 365 + isleapyear(year); year--; } std::vector mdays = month_days(year); for (int i=0; i<(ymd[1]-1); i++) { day += mdays[i]; } day += ymd[2]; } return(day); } bool SpatDate::is_leap_year() { std::vector d = ymd(); return isleapyear( d[0] ); } SpatDate::SpatDate(const int& year, const int& month, const int& day) { std::vector ymd {year, month, day}; v = date_from_ymd(ymd); } SpatDate::SpatDate(int doy, int year) { if (doy == 0) doy = 1; if (doy < 0) { // this is a weird case, but let's try to handle it while ( doy < 0 ) { year--; doy = doy + 365 + isleapyear(year); } doy = 365 + isleapyear(year) - doy; } else { while ( doy > 366 ) { doy = doy - 365 - isleapyear(year); year++; } } std::vector mdays = month_days(year); int month= 0 ; while ( doy > mdays[month] ) { doy = doy - mdays[month]; month++; } SpatDate(year, month+1, doy); } int SpatDate::doy() { std::vector d = ymd(); std::vector mdays = month_days(d[0]); int doy = 0; for (int i=0; i < d[1]-1; i++) { doy = doy + mdays[i]; } return( doy + d[2] ); } bool operator == (const SpatDate& d1,const SpatDate& d2){ return (d1.v == d2.v); } bool operator !=(const SpatDate& d1, const SpatDate& d2){ return (d1.v != d2.v); } inline SpatDate next_date(const SpatDate& d) { SpatDate x(d.v+1); return x; } inline SpatDate previous_date(const SpatDate& d){ SpatDate x(d.v-1); return x; } SpatDate SpatDate::operator ++(int){ SpatDate d = *this; *this = next_date(d); return d; } SpatDate SpatDate::operator ++() { *this = next_date(*this); return *this; } SpatDate SpatDate::operator --(int){ SpatDate d = *this; *this = previous_date(d); return d; } SpatDate SpatDate::operator --(){ *this = previous_date(*this); return *this; } bool operator < (const SpatDate& d1, const SpatDate& d2){ return (d1.v < d2.v); } bool operator <=(const SpatDate& d1, const SpatDate& d2){ return (d1.v <= d2.v); } bool operator >=(const SpatDate& d1, const SpatDate& d2) { return (d1.v >= d2.v); } bool operator > (const SpatDate& d1, const SpatDate& d2) { return (d1.v > d2.v); } int operator - (SpatDate& d1, SpatDate& d2) { return (d1.v - d2.v); } SpatDate operator +(SpatDate &d1, int x){ return SpatDate(d1.v + x); } SpatDate operator +(int x, SpatDate &d1) { return SpatDate(d1.v + x); } SpatDate operator -(SpatDate &d1, int x){ return SpatDate(d1.v - x); } void SpatDate::operator =(const SpatDate &d){ this->v = d.v; } #endif terra/src/geosphere.cpp0000644000175000017500000002706214201035750015001 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include "spatVector.h" #include "geodesic.h" #include "recycle.h" #ifndef M_PI #define M_PI (3.1415926535897932384626433) #endif #ifndef M_2PI #define M_2PI (3.1415926535897932384626433 * 2.0) #endif #ifndef M_PI_2 #define M_PI_2 (3.1415926535897932384626433 / 2) #endif #ifndef WGS84_a #define WGS84_a 6378137.0; #endif #ifndef WGS84_f #define WGS84_f 1/298.257223563;; #endif inline void normLon(double &lon) { lon = fmod(lon + 180, 360.) - 180; } inline void normLonRad(double &lon) { lon = fmod(lon + M_PI, M_2PI) - M_PI; } inline double get_sign(double x) { if (x > 0.0) return 1.0; if (x < 0.0) return -1.0; return x; } // [[Rcpp::export]] double dist_lonlat(const double &lon1, const double &lat1, const double &lon2, const double &lat2) { double a = 6378137.0; double f = 1/298.257223563; double s12, azi1, azi2; struct geod_geodesic g; geod_init(&g, a, f); geod_inverse(&g, lat1, lon1, lat2, lon2, &s12, &azi1, &azi2); return s12; } void dest_lonlat(double slon, double slat, double sazi, double dist, double &dlon, double &dlat, double &dazi) { double a = 6378137.0; double f = 1/298.257223563; struct geod_geodesic g; geod_init(&g, a, f); geod_direct(&g, slat, slon, sazi, dist, &dlat, &dlon, &dazi); } // [[Rcpp::export]] double dir_lonlat(double lon1, double lat1, double lon2, double lat2) { double a = 6378137.0; double f = 1/298.257223563; double s12, azi1, azi2; struct geod_geodesic g; geod_init(&g, a, f); geod_inverse(&g, lat1, lon1, lat2, lon2, &s12, &azi1, &azi2); return( azi1) ; } // [[Rcpp::export]] double dist2track(double lon1, double lat1, double lon2, double lat2, double plon, double plat, bool sign) { double a = 1; double f = 0; struct geod_geodesic geod; geod_init(&geod, a, f); double r = 6378137.0; double d, b2, b3, azi; geod_inverse(&geod, lat1, lon1, lat2, lon2, &d, &b2, &azi); geod_inverse(&geod, lat1, lon1, plat, plon, &d, &b3, &azi); double toRad = M_PI / 180.; b2 *= toRad; b3 *= toRad; double xtr = asin(sin(b3-b2) * sin(d)) * r; if (!sign) xtr = fabs(xtr); return xtr; } // [[Rcpp::export]] double alongTrackDistance(double lon1, double lat1, double lon2, double lat2, double plon, double plat) { double a = 1; double f = 0; struct geod_geodesic geod; geod_init(&geod, a, f); double r = 6378137.0; double d, b2, b3, azi; geod_inverse(&geod, lat1, lon1, lat2, lon2, &d, &b2, &azi); geod_inverse(&geod, lat1, lon1, plat, plon, &d, &b3, &azi); double toRad = M_PI / 180.; b2 *= toRad; b3 *= toRad; double xtr = asin(sin(b3-b2) * sin(d)); double bsign = get_sign(cos(b2-b3)); return fabs(bsign * acos(cos(d) / cos(xtr)) * r); } #include "Rcpp.h" // [[Rcpp::export]] double dist2segment(double plon, double plat, double lon1, double lat1, double lon2, double lat2) { // the alongTrackDistance is the length of the path along the great circle to the point of intersection // there are two, depending on which node you start // we want to use the min, but the max needs to be < segment length double seglength = dist_lonlat(lon1, lat1, lon2, lat2); double trackdist1 = alongTrackDistance(lon1, lat1, lon2, lat2, plon, plat); double trackdist2 = alongTrackDistance(lon2, lat2, lon1, lat1, plon, plat); if ((trackdist1 >= seglength) || (trackdist2 >= seglength)) { double d1 = dist_lonlat(lon1, lat1, plon, plat); double d2 = dist_lonlat(lon2, lat2, plon, plat); return d1 < d2 ? d1 : d2; } return dist2track(lon1, lat1, lon2, lat2, plon, plat, false); } // [[Rcpp::export]] double dist2segmentPoint(double plon, double plat, double lon1, double lat1, double lon2, double lat2, double &ilon, double &ilat) { double seglength = dist_lonlat(lon1, lat1, lon2, lat2); double trackdist1 = alongTrackDistance(lon1, lat1, lon2, lat2, plon, plat); double trackdist2 = alongTrackDistance(lon2, lat2, lon1, lat1, plon, plat); if ((trackdist1 >= seglength) || (trackdist2 >= seglength)) { double d1 = dist_lonlat(lon1, lat1, plon, plat); double d2 = dist_lonlat(lat2, lat2, plon, plat); if (d1 < d2) { ilon = lon1; ilat = lat1; return d1; } else { ilon = lon2; ilat = lat2; return d2; } } double azi; double crossd = dist2track(lon1, lat1, lon2, lat2, plon, plat, false); if (trackdist1 < trackdist2) { double bear = dir_lonlat(lon1, lat1, lon2, lat2); dest_lonlat(lon1, lat1, bear, trackdist1, ilon, ilat, azi); } else { double bear = dir_lonlat(lon2, lat2, lon1, lat1); dest_lonlat(lon2, lat2, bear, trackdist2, ilon, ilat, azi); } return(crossd); } std::vector SpatVector::linedistLonLat(SpatVector x) { std::vector> pxy = x.coordinates(); size_t np = pxy[0].size(); size_t ng = size(); std::vector d, dd; dd.reserve(np*ng); d.resize(np); bool poly = type() == "polygons"; if (poly) { SpatVector pg; pg.srs = srs; std::vector insect; for (size_t g=0; g> xy = geoms[g].coordinates(); size_t nseg = xy[0].size() - 1; for (size_t i=0; i> xy = geoms[g].coordinates(); size_t nseg = xy[0].size() - 1; for (size_t i=0; i> intermediate(double lon1, double lat1, double lon2, double lat2, int n, double distance) { double a = 6378137.0; double f = 1/298.257223563; struct geod_geodesic geod; geod_init(&geod, a, f); double d, azi1, azi2; std::vector> out(2); if (n <= 0) { if (distance <= 0) { out[0] = {lon1, lon2}; out[1] = {lon1, lon2}; return out; } else { geod_inverse(&geod, lat1, lon1, lat2, lon2, &d, &azi1, &azi2); n = std::round(d / distance); if (n < 2) { out[0] = {lon1, lon2}; out[1] = {lon1, lon2}; return out; } distance = d / n; } } else if (n == 1) { out[0] = {lon1, lon2}; out[1] = {lon1, lon2}; return out; } else { geod_inverse(&geod, lat1, lon1, lat2, lon2, &d, &azi1, &azi2); //distance = d / n; } out[0].resize(n+1); out[1].resize(n+1); out[0][0] = lon1; out[1][0] = lat1; for (int i=1; i &lon, std::vector &lat, double &interval, bool &adjust, geod_geodesic &g) { size_t np = lon.size(); if (np < 2) { return; } size_t sz = lon.size() * 5; std::vector xout, yout; xout.reserve(sz); yout.reserve(sz); for (size_t i=0; i<(np-1); i++) { if (xout.size() > sz) { sz += (np-i) * 10; xout.reserve(sz); yout.reserve(sz); } double d, azi1, azi2; geod_inverse(&g, lat[i], lon[i], lat[i+1], lon[i+1], &d, &azi1, &azi2); size_t n = floor(d / interval); xout.push_back(lon[i]); yout.push_back(lat[i]); if (n < 2) { continue; } double step = adjust ? d / n : d; double newlat, newlon; for (size_t j=1; j &x, std::vector &y, double &interval, bool &adjust) { size_t np = x.size(); if (np < 2) { return; } size_t sz = x.size() * 5; std::vector xout, yout; xout.reserve(sz); yout.reserve(sz); double pi2 = M_PI * 2; for (size_t i=0; i<(np-1); i++) { if (xout.size() > sz) { sz += (np-i) * 10; xout.reserve(sz); yout.reserve(sz); } double d = sqrt(pow((x[i+1] - x[i]),2) + pow((y[i+1] - y[i]), 2)); size_t n = floor(d / interval); xout.push_back(x[i]); yout.push_back(y[i]); if (n < 2) { continue; } double a = fmod(atan2(x[i+1]-x[i], y[i+1]-y[i]), pi2); double step = adjust ? d / n : interval; double distx = step * sin(a); double disty = step * cos(a); for (size_t j=1; j 0"); return out; } out.srs = srs; if (srs.is_empty()) { out.setError("crs not defined"); return(out); } if (is_lonlat()) { double a = 6378137.0; double f = 1/298.257223563; struct geod_geodesic geod; geod_init(&geod, a, f); for (size_t i=0; i antipodal(std::vector lon1, std::vector lat1, std::vector lon2, std::vector lat2, double tol=1e-9) { recycle(lon1, lon2); recycle(lat1, lat2); std::vector out; out.reserve(lon1.size()); double Pi180 = M_PI / 180.; for (size_t i=0; i &lon, std::vector &lat) { size_t n=lon.size(); for (size_t i=0; i #include "spatRaster.h" SpatRaster SpatRaster::applyGCP(std::vector fx, std::vector fy, std::vector tx, std::vector ty, SpatOptions &opt) { SpatRaster out; std::vector cls = cellFromXY(fx, fy); std::vector> rc = rowColFromCell(cls); GDAL_GCP *gcps = NULL; gcps = (GDAL_GCP *) CPLRealloc (gcps, (fx.size()) * sizeof(GDAL_GCP)); GDALInitGCPs(fx.size(), gcps); for (size_t i = 0; i < fx.size(); i++){ gcps[i].dfGCPPixel = rc[1][i]; gcps[i].dfGCPLine = rc[0][i]; gcps[i].dfGCPX = tx[i]; gcps[i].dfGCPY = ty[i]; gcps[i].dfGCPZ = (float) 0.0; } GDALDatasetH hSrcDS; //hDstDS, if (!open_gdal(hSrcDS, 0, false, opt)) { out.setError("bad"); return out; } std::string srccrs = getSRS("wkt"); const char *projection = srccrs.c_str(); GDALSetGCPs(hSrcDS, fx.size(), gcps, projection); //if (!get_output_bounds(hSrcDS, srccrs, srccrs, out)) { // GDALClose( hSrcDS ); // return out; //} return out; } terra/src/gdal_algs.cpp0000644000175000017500000010455114202037503014733 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include "gdalwarper.h" #include "ogr_spatialref.h" #include "gdal_alg.h" #include "ogrsf_frmts.h" #include "spatRaster.h" #include "string_utils.h" #include "file_utils.h" #include "vecmath.h" #include "crs.h" #include "gdalio.h" #include "recycle.h" //#include //#include "vecmath.h" SpatVector SpatRaster::dense_extent(bool inside, bool geobounds) { SpatExtent e = getExtent(); if (geobounds && is_lonlat() && ((e.ymin < -90) || (e.ymax > 90))) { SpatRaster g = geometry(); e.ymin= std::max(e.ymin, -90.0); e.ymax= std::min(e.ymax, 90.0); g.source[0].extent = e; return g.dense_extent(inside, false); } std::vector rows, cols; if (nrow() < 51) { rows.resize(nrow()); std::iota(rows.begin(), rows.end(), 0); } else { rows = seq_steps((int_64) 0, (int_64) nrow()-1, 50); } if (ncol() < 51) { cols.resize(nrow()); std::iota(cols.begin(), cols.end(), 0); } else { cols = seq_steps((int_64) 0, (int_64) ncol()-1, 50); } std::vector xcol = xFromCol(cols) ; std::vector yrow = yFromRow(rows) ; double yr = yres() / 4; if (inside) { yrow.insert(yrow.begin(), e.ymax - yr); yrow.push_back(e.ymin + yr); std::vector y0(xcol.size(), e.ymin+yr); std::vector y1(xcol.size(), e.ymax-yr); } else { yrow.insert(yrow.begin(), e.ymax); yrow.push_back(e.ymin); std::vector y0(xcol.size(), e.ymin); std::vector y1(xcol.size(), e.ymax); } std::vector y0(xcol.size(), e.ymin); std::vector y1(xcol.size(), e.ymax); std::vector x0(yrow.size(), e.xmin); std::vector x1(yrow.size(), e.xmax); std::vector x = x0; std::vector y = yrow; x.insert(x.end(), xcol.begin(), xcol.end()); y.insert(y.end(), y0.begin(), y0.end()); std::reverse(yrow.begin(), yrow.end()); std::reverse(xcol.begin(), xcol.end()); x.insert(x.end(), x1.begin(), x1.end()); y.insert(y.end(), yrow.begin(), yrow.end() ); x.insert(x.end(), xcol.begin(), xcol.end()); y.insert(y.end(), y1.begin(), y1.end()); x.push_back(x[0]); y.push_back(y[0]); SpatVector v(x, y, polygons, getSRS("wkt")); return v; } #if GDAL_VERSION_MAJOR <= 2 && GDAL_VERSION_MINOR < 2 SpatRaster SpatRaster::warper(SpatRaster x, std::string crs, std::string method, bool mask, bool align, SpatOptions &opt) { SpatRaster out; out.setError("Not supported for this old version of GDAL"); return(out); } #else bool get_output_bounds(const GDALDatasetH &hSrcDS, std::string srccrs, const std::string dstcrs, SpatRaster &r) { if ( hSrcDS == NULL ) { r.setError("data source is NULL"); return false; } // Get Source coordinate system. // const char *pszSrcWKT = GDALGetProjectionRef( hSrcDS ); const char *pszSrcWKT = srccrs.c_str(); if ( pszSrcWKT == NULL || strlen(pszSrcWKT) == 0 ) { r.setError("data source has no WKT"); return false; } OGRSpatialReference* oSRS = new OGRSpatialReference; std::string msg = ""; if (is_ogr_error(oSRS->SetFromUserInput( dstcrs.c_str() ), msg)) { r.setError(msg); return false; }; char *pszDstWKT = NULL; oSRS->exportToWkt( &pszDstWKT ); // Create a transformer that maps from source pixel/line coordinates // to destination georeferenced coordinates (not destination // pixel line). We do that by omitting the destination dataset // handle (setting it to NULL). void *hTransformArg; hTransformArg = GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, NULL, pszDstWKT, FALSE, 0, 1 ); if (hTransformArg == NULL ) { r.setError("cannot create TranformArg"); return false; } CPLFree(pszDstWKT); delete oSRS; double adfDstGeoTransform[6]; int nPixels=0, nLines=0; CPLErr eErr = GDALSuggestedWarpOutput( hSrcDS, GDALGenImgProjTransform, hTransformArg, adfDstGeoTransform, &nPixels, &nLines ); GDALDestroyGenImgProjTransformer( hTransformArg ); if ( eErr != CE_None ) { r.setError("cannot create warp output"); return false; } r.source[0].ncol = nPixels; r.source[0].nrow = nLines; r.source[0].extent.xmin = adfDstGeoTransform[0]; /* left x */ /* w-e pixel resolution */ r.source[0].extent.xmax = r.source[0].extent.xmin + adfDstGeoTransform[1] * nPixels; r.source[0].extent.ymax = adfDstGeoTransform[3]; // top y r.source[0].extent.ymin = r.source[0].extent.ymax + nLines * adfDstGeoTransform[5]; r.setSRS({dstcrs}); return true; } /* // Create output with same datatype as first input band. GDALDataType eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1)); GDALDataType eDT; getGDALDataType(datatype, eDT); // Create the output DS. GDALDriverH hDriver = GDALGetDriverByName( driver.c_str() ); if ( hDriver == NULL ) { msg = "empty driver"; return false; } if (driver == "MEM") { hDstDS = GDALCreate( hDriver, "", nPixels, nLines, nlyrs, eDT, NULL ); } else { hDstDS = GDALCreate( hDriver, filename.c_str(), nPixels, nLines, nlyrs, eDT, NULL ); } if ( hDstDS == NULL ) { msg = "cannot create output dataset"; return false; } // Write out the projection definition. GDALSetProjection( hDstDS, pszDstWKT ); GDALSetGeoTransform( hDstDS, adfDstGeoTransform ); // Copy the color table, if required. GDALColorTableH hCT; hCT = GDALGetRasterColorTable( GDALGetRasterBand(hSrcDS,1) ); if( hCT != NULL ) GDALSetRasterColorTable( GDALGetRasterBand(hDstDS,1), hCT ); CPLFree(pszDstWKT); delete oSRS; return true; } */ bool getAlgo(GDALResampleAlg &alg, std::string m) { if (m=="sum") { #if GDAL_VERSION_MAJOR >= 3 && GDAL_VERSION_MINOR >= 1 alg = GRA_Sum; return true; } #else return false; } #endif if (m=="rms") { #if GDAL_VERSION_MAJOR >= 3 && GDAL_VERSION_MINOR >= 3 alg = GRA_RMS; return true; } #else return false; } #endif if ( m == "near" ) { alg = GRA_NearestNeighbour; } else if (m=="bilinear") { alg = GRA_Bilinear; } else if (m=="cubic") { alg = GRA_Cubic; } else if (m=="cubicspline") { alg = GRA_CubicSpline; } else if (m=="lanczos") { alg = GRA_Lanczos; } else if (m=="average") { alg = GRA_Average; } else if (m=="mode") { alg = GRA_Mode; } else if (m=="max") { alg = GRA_Max; } else if (m=="min") { alg = GRA_Min; } else if (m=="median") { alg = GRA_Med; } else if (m=="q1") { alg = GRA_Q1; } else if (m=="q3") { alg = GRA_Q3; } else { alg = GRA_NearestNeighbour; return false; } return true; } bool is_valid_warp_method(const std::string &method) { std::vector m { "near", "bilinear", "cubic", "cubicspline", "lanczos", "average", "mode", "max", "min", "med", "q1", "q3", "sum", "rms"}; return (std::find(m.begin(), m.end(), method) != m.end()); } bool set_warp_options(GDALWarpOptions *psWarpOptions, GDALDatasetH &hSrcDS, GDALDatasetH &hDstDS, std::vector srcbands, std::vector dstbands, std::string method, std::string srccrs, std::string msg, bool verbose, bool threads) { if (srcbands.size() != dstbands.size()) { msg = "number of source bands must match number of dest bands"; return false; } int nbands = srcbands.size(); GDALResampleAlg a; if (!getAlgo(a, method)) { if (method=="sum" || method=="rms") { msg = method + " not available in your version of GDAL"; } else { msg = "unknown resampling algorithm"; } return false; } // Setup warp options. psWarpOptions->hSrcDS = hSrcDS; psWarpOptions->hDstDS = hDstDS; psWarpOptions->eResampleAlg = a; psWarpOptions->nBandCount = nbands; psWarpOptions->panSrcBands = (int *) CPLMalloc(sizeof(int) * nbands ); psWarpOptions->panDstBands = (int *) CPLMalloc(sizeof(int) * nbands ); psWarpOptions->padfSrcNoDataReal = (double *) CPLMalloc(sizeof(double) * nbands ); psWarpOptions->padfDstNoDataReal = (double *) CPLMalloc(sizeof(double) * nbands ); psWarpOptions->padfSrcNoDataImag = (double *) CPLMalloc(sizeof(double) * nbands ); psWarpOptions->padfDstNoDataImag = (double *) CPLMalloc(sizeof(double) * nbands ); GDALRasterBandH hBand; int hasNA; for (int i=0; ipanSrcBands[i] = (int) srcbands[i]+1; psWarpOptions->panDstBands[i] = (int) dstbands[i]+1; hBand = GDALGetRasterBand(hSrcDS, srcbands[i]+1); double naflag = GDALGetRasterNoDataValue(hBand, &hasNA); if (verbose && i == 0) { #ifdef useRcpp std::string hna = hasNA ? "true" : "false"; Rcpp::Rcout << "hasNA : " << hna << std::endl; Rcpp::Rcout << "NA flag : " << naflag << std::endl; #endif } if (hasNA) { psWarpOptions->padfSrcNoDataReal[i] = naflag; psWarpOptions->padfDstNoDataReal[i] = naflag; hBand = GDALGetRasterBand(hDstDS, dstbands[i]+1); GDALSetRasterNoDataValue(hBand, naflag); } else { psWarpOptions->padfSrcNoDataReal[i] = NAN; psWarpOptions->padfDstNoDataReal[i] = NAN; } psWarpOptions->padfSrcNoDataImag[i] = 0; psWarpOptions->padfDstNoDataImag[i] = 0; } //psWarpOptions->pfnProgress = GDALTermProgress; psWarpOptions->papszWarpOptions = CSLSetNameValue( psWarpOptions->papszWarpOptions, "INIT_DEST", "NO_DATA"); psWarpOptions->papszWarpOptions = CSLSetNameValue( psWarpOptions->papszWarpOptions, "WRITE_FLUSH", "YES"); if (threads) { psWarpOptions->papszWarpOptions = CSLSetNameValue( psWarpOptions->papszWarpOptions, "NUM_THREADS", "ALL_CPUS"); } psWarpOptions->pTransformerArg = GDALCreateGenImgProjTransformer( hSrcDS, srccrs.c_str(), hDstDS, GDALGetProjectionRef(hDstDS), FALSE, 0.0, 1 ); psWarpOptions->pfnTransformer = GDALGenImgProjTransform; return true; } bool gdal_warper(GDALWarpOptions *psWarpOptions, GDALDatasetH &hSrcDS, GDALDatasetH &hDstDS) { GDALWarpOperation oOperation; if (oOperation.Initialize( psWarpOptions ) != CE_None) { return false; } oOperation.ChunkAndWarpImage( 0, 0, GDALGetRasterXSize( hDstDS ), GDALGetRasterYSize( hDstDS ) ); GDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg ); GDALDestroyWarpOptions( psWarpOptions ); return true; } SpatRaster SpatRaster::warper(SpatRaster x, std::string crs, std::string method, bool mask, bool align, SpatOptions &opt) { SpatRaster out = x.geometry(nlyr(), false, false); out.setNames(getNames()); if (method == "near") { out.source[0].hasColors = hasColors(); out.source[0].cols = getColors(); out.source[0].hasCategories = hasCategories(); out.source[0].cats = getCategories(); out.rgb = rgb; out.rgblyrs = rgblyrs; out.rgbtype = rgbtype; } if (hasTime()) { out.source[0].hasTime = true; out.source[0].timestep = getTimeStep(); out.source[0].time = getTime(); } bool use_crs = crs != ""; if (use_crs) { align = false; } if (align) { crs = out.getSRS("wkt"); } if ((!use_crs) & (!hasValues())) { std::string fname = opt.get_filename(); if (fname != "") { out.addWarning("raster has no values, not writing to file"); } return out; } if (!is_valid_warp_method(method)) { out.setError("not a valid warp method"); return out; } std::string srccrs = getSRS("wkt"); if (srccrs == "") { out.setError("input raster CRS not set"); return out; } lrtrim(crs); SpatOptions sopt(opt); if (use_crs || align) { GDALDatasetH hSrcDS; if (!open_gdal(hSrcDS, 0, false, sopt)) { out.setError("cannot create dataset from source"); return out; } if (!get_output_bounds(hSrcDS, srccrs, crs, out)) { GDALClose( hSrcDS ); out.setError("cannot get output boundaries"); return out; } GDALClose( hSrcDS ); } if (align) { SpatExtent e = out.getExtent(); e = x.align(e, "out"); out.setExtent(e, false); std::vector res = x.resolution(); out = out.setResolution(res[0], res[1]); } if (!hasValues()) { return out; } SpatOptions mopt; if (mask) { mopt = opt; opt = SpatOptions(opt); } opt.ncopies += 4; if (!out.writeStart(opt)) { return out; } std::string errmsg; size_t ns = nsrc(); SpatExtent eout = out.getExtent(); std::vector has_so = source[0].has_scale_offset; std::vector scale = source[0].scale; std::vector offset = source[0].offset; for (size_t i=1; i srcbands = source[i].layers; std::vector dstbands(srcbands.size()); std::iota (dstbands.begin(), dstbands.end(), bandstart); bandstart += dstbands.size(); GDALWarpOptions *psWarpOptions = GDALCreateWarpOptions(); bool ok = set_warp_options(psWarpOptions, hSrcDS, hDstDS, srcbands, dstbands, method, srccrs, errmsg, opt.get_verbose(), opt.threads); if (!ok) { if( hDstDS != NULL ) GDALClose( (GDALDatasetH) hDstDS ); out.setError(errmsg); return out; } //bool success = gdal_warper(hSrcDS, hDstDS, srcbands, dstbands, method, srccrs, errmsg, opt.get_verbose(), opt.threads); ok = gdal_warper(psWarpOptions, hSrcDS, hDstDS); if( hSrcDS != NULL ) GDALClose( (GDALDatasetH) hSrcDS ); if (!ok) { if( hDstDS != NULL ) GDALClose( (GDALDatasetH) hDstDS ); out.setError("warp failure"); return out; } } bool ok = crop_out.from_gdalMEM(hDstDS, false, true); if( hDstDS != NULL ) GDALClose( (GDALDatasetH) hDstDS ); if (!ok) { out.setError("cannot do this transformation (warp)"); return out; } std::vector v = crop_out.getValues(-1, opt); if (!out.writeBlock(v, i)) return out; } out.writeStop(); if (mask) { SpatVector v = dense_extent(true, true); v = v.project(out.getSRS("wkt")); if (v.nrow() > 0) { out = out.mask(v, false, NAN, true, mopt); } else { out.addWarning("masking failed"); } } return out; } #endif SpatRaster SpatRaster::resample(SpatRaster x, std::string method, bool mask, bool agg, SpatOptions &opt) { unsigned nl = nlyr(); SpatRaster out = x.geometry(nl); out.setNames(getNames()); out.setNames(getNames()); std::vector f {"bilinear", "near"}; if (std::find(f.begin(), f.end(), method) == f.end()) { out.setError("unknown warp method"); return out; } if (!hasValues()) { return out; } std::string crsin = source[0].srs.wkt; std::string crsout = out.source[0].srs.wkt; bool do_prj = true; if ((crsin == crsout) || (crsin == "") || (crsout == "")) { do_prj = false; } if (!do_prj) { SpatExtent e = out.getExtent(); e = e.intersect(getExtent()); if (!e.valid()) { out.addWarning("No spatial overlap"); return out; } } if (agg) { if (do_prj) { // compare changes in true cell areas // if (some) output cells are much larger than input, we could // a) disaggregate "x", warp, and aggregate the results // b) or give a warning? } else { unsigned xq = x.xres() / xres(); unsigned yq = x.yres() / yres(); if (std::max(xq, yq) > 1) { xq = xq == 0 ? 1 : xq; yq = yq == 0 ? 1 : yq; std::vector agf = {yq, xq, 1}; SpatOptions agopt(opt); SpatRaster xx; if (method == "bilinear") { xx = aggregate(agf, "mean", true, agopt); } else { xx = aggregate(agf, "modal", true, agopt); } return xx.resample(x, method, mask, false, opt); } } } SpatOptions mopt; if (mask) { mopt = opt; opt = SpatOptions(opt); } unsigned nc = out.ncol(); if (!out.writeStart(opt)) { return out; } for (size_t i = 0; i < out.bs.n; i++) { unsigned firstcell = out.cellFromRowCol(out.bs.row[i], 0); unsigned lastcell = out.cellFromRowCol(out.bs.row[i]+out.bs.nrows[i]-1, nc-1); std::vector cells(1+lastcell-firstcell); std::iota (std::begin(cells), std::end(cells), firstcell); std::vector> xy = out.xyFromCell(cells); if (do_prj) { #ifdef useGDAL out.msg = transform_coordinates(xy[0], xy[1], crsout, crsin); #else out.setError("GDAL is needed for crs transformation, but not available"); return out; #endif } std::vector> e = extractXY(xy[0], xy[1], method, false); std::vector v = flatten(e); if (!out.writeValues(v, out.bs.row[i], out.bs.nrows[i])) return out; } out.writeStop(); if (mask) { SpatVector v = dense_extent(true, true); v = v.project(out.getSRS("wkt")); if (v.nrow() > 0) { out = out.mask(v, false, NAN, true, mopt); } else { out.addWarning("masking failed"); } } return(out); } SpatRaster SpatRaster::rectify(std::string method, SpatRaster aoi, unsigned useaoi, bool snap, SpatOptions &opt) { SpatRaster out = geometry(0); if (nsrc() > 1) { out.setError("you can transform only one data source at a time"); return(out); } if (!source[0].rotated) { out.setError("this source is not rotated"); return(out); } GDALDataset *poDataset = openGDAL(source[0].filename, GDAL_OF_RASTER | GDAL_OF_READONLY, source[0].open_ops); if( poDataset == NULL ) { setError("cannot read from " + source[0].filename); return out; } double gt[6]; if( poDataset->GetGeoTransform(gt) != CE_None ) { out.setError("can't get geotransform"); GDALClose( (GDALDatasetH) poDataset ); return out; } GDALClose( (GDALDatasetH) poDataset ); //SpatExtent e = getExtent(); //std::vector x = {e.xmin, e.xmin, e.xmax, e.xmax }; //std::vector y = {e.ymin, e.ymax, e.ymin, e.ymax }; double nc = ncol(); double nr = nrow(); std::vector x = {0, 0, nc, nc}; std::vector y = {0, nr, 0, nr}; std::vector xx(4); std::vector yy(4); for (size_t i=0; i<4; i++) { xx[i] = gt[0] + x[i]*gt[1] + y[i]*gt[2]; yy[i] = gt[3] + x[i]*gt[4] + y[i]*gt[5]; } double xmin = vmin(xx, TRUE); double xmax = vmax(xx, TRUE); double ymin = vmin(yy, TRUE); double ymax = vmax(yy, TRUE); SpatExtent en(xmin, xmax, ymin, ymax); out = out.setResolution(gt[1], -gt[5]); out.setExtent(en, false, "out"); if (useaoi == 1) { // use extent en = aoi.getExtent(); if (snap) { en = out.align(en, "near"); out.setExtent(en, false, "near"); } else { out.setExtent(en, false, ""); } } else if (useaoi == 2){ // extent and resolution out = aoi.geometry(0); } // else { // if (useaoi == 0) // no aoi out = warper(out, "", method, false, false, opt); return(out); } SpatVector SpatRaster::polygonize(bool trunc, bool values, bool narm, bool aggregate, SpatOptions &opt) { SpatVector out; out.srs = source[0].srs; SpatOptions topt(opt); SpatRaster tmp; if (nlyr() > 1) { out.addWarning("only the first layer is polygonized when 'dissolve=TRUE'"); tmp = subset({0}, topt); } else { tmp = *this; } // bool usemask = false; SpatRaster mask; if (narm) { // usemask = true; SpatOptions mopt(topt); mopt.set_datatype("INT1U"); mask = tmp.isfinite(mopt); } else if (trunc) { tmp = tmp.math("trunc", topt); trunc = false; } else if (tmp.sources_from_file()) { // for NAN and INT files. Should have a check for that //tmp = tmp.arith(0, "+", false, topt); // riskier tmp.readAll(); } if (tmp.source[0].extset) { tmp = tmp.hardCopy(topt); } GDALDatasetH rstDS; if (!tmp.open_gdal(rstDS, 0, false, topt)) { out.setError("cannot open dataset"); return out; } GDALDataset *srcDS=NULL; #if GDAL_VERSION_MAJOR <= 2 && GDAL_VERSION_MINOR <= 2 srcDS = (GDALDataset *) rstDS; #else srcDS = srcDS->FromHandle(rstDS); #endif GDALDataset *maskDS=NULL; GDALDatasetH rstMask; if (narm) { if (!mask.open_gdal(rstMask, 0, false, opt)) { out.setError("cannot open dataset"); return out; } #if GDAL_VERSION_MAJOR <= 2 && GDAL_VERSION_MINOR <= 2 maskDS = (GDALDataset *) rstMask; #else maskDS = srcDS->FromHandle(rstMask); #endif } GDALDataset *poDS = NULL; GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName( "Memory" ); if( poDriver == NULL ) { out.setError( "cannot create output driver"); return out; } poDS = poDriver->Create("", 0, 0, 0, GDT_Unknown, NULL ); if( poDS == NULL ) { out.setError("Creation of output dataset failed" ); return out; } std::vector nms = getNames(); std::string name = nms[0]; OGRSpatialReference *SRS = NULL; OGRLayer *poLayer; poLayer = poDS->CreateLayer(name.c_str(), SRS, wkbPolygon, NULL ); if( poLayer == NULL ) { out.setError( "Layer creation failed" ); return out; } if (SRS != NULL) SRS->Release(); OGRFieldDefn oField(name.c_str(), trunc ? OFTInteger : OFTReal); if( poLayer->CreateField( &oField ) != OGRERR_NONE ) { out.setError( "Creating field failed"); return out; } GDALRasterBand *poBand; poBand = srcDS->GetRasterBand(1); //int hasNA=1; //double naflag = poBand->GetNoDataValue(&hasNA); CPLErr err; if (narm) { GDALRasterBand *maskBand; maskBand = maskDS->GetRasterBand(1); if (trunc) { err = GDALPolygonize(poBand, maskBand, poLayer, 0, NULL, NULL, NULL); } else { err = GDALFPolygonize(poBand, maskBand, poLayer, 0, NULL, NULL, NULL); } GDALClose(maskDS); } else { if (trunc) { err = GDALPolygonize(poBand, NULL, poLayer, 0, NULL, NULL, NULL); } else { err = GDALFPolygonize(poBand, NULL, poLayer, 0, NULL, NULL, NULL); } } if (err == 4) { out.setError("polygonize error"); return out; } GDALClose(srcDS); std::vector fext; SpatVector fvct; out.read_ogr(poDS, "", "", fext, fvct, false); GDALClose(poDS); if (aggregate && (out.nrow() > 0)) { out = out.aggregate(name, false); } if (!values) { out.df = SpatDataFrame(); } return out; } SpatRaster SpatRaster::rgb2col(size_t r, size_t g, size_t b, SpatOptions &opt) { SpatRaster out = geometry(1); if (nlyr() < 3) { out.setError("need at least three layers"); return out; } size_t mxlyr = std::max(std::max(r, g), b); if (nlyr() < mxlyr) { out.setError("layer number for R, G, B, cannot exceed nlyr()"); return out; } std::string filename = opt.get_filename(); opt.set_datatype("INT1U"); std::string driver; if (filename == "") { if (canProcessInMemory(opt)) { driver = "MEM"; } else { filename = tempFile(opt.get_tempdir(), opt.pid, ".tif"); opt.set_filenames({filename}); driver = "GTiff"; } } else { driver = opt.get_filetype(); getGDALdriver(filename, driver); if (driver == "") { setError("cannot guess file type from filename"); return out; } std::string errmsg; if (!can_write(filename, opt.get_overwrite(), errmsg)) { out.setError(errmsg); return out; } } std::vector lyrs = {(unsigned)r, (unsigned)g, (unsigned)b}; SpatOptions ops(opt); *this = subset(lyrs, ops); *this = collapse_sources(); GDALDatasetH hSrcDS, hDstDS; if (!open_gdal(hSrcDS, 0, false, ops)) { out.setError("cannot create dataset from source"); return out; } GDALRasterBandH R = GDALGetRasterBand(hSrcDS,1); GDALRasterBandH G = GDALGetRasterBand(hSrcDS,1); GDALRasterBandH B = GDALGetRasterBand(hSrcDS,1); GDALColorTableH hColorTable= GDALCreateColorTable(GPI_RGB); if (GDALComputeMedianCutPCT(R, G, B, NULL, 256, hColorTable, NULL, NULL) != CE_None) { out.setError("cannot create color table"); GDALClose(hSrcDS); return out; } if (!out.create_gdalDS(hDstDS, filename, driver, true, 0, {false}, {0.0}, {1.0}, opt)) { out.setError("cannot create new dataset"); GDALClose(hSrcDS); return out; } GDALRasterBandH hTarget = GDALGetRasterBand(hDstDS, 1); GDALSetRasterColorInterpretation(hTarget, GCI_PaletteIndex); if (GDALDitherRGB2PCT(R, G, B, hTarget, hColorTable, NULL, NULL) != CE_None) { out.setError("cannot set color table"); GDALClose(hSrcDS); GDALClose(hDstDS); return out; } GDALClose(hSrcDS); if (driver == "MEM") { if (!out.from_gdalMEM(hDstDS, false, true)) { out.setError("conversion failed (mem)"); GDALClose(hDstDS); return out; } SpatDataFrame cdf; cdf.add_column(1, "red"); cdf.add_column(1, "green"); cdf.add_column(1, "blue"); cdf.add_column(1, "alpha"); size_t nc = GDALGetColorEntryCount(hColorTable); cdf.reserve(nc); for (size_t i=0; ic1); cdf.iv[1].push_back(col->c2); cdf.iv[2].push_back(col->c3); cdf.iv[3].push_back(col->c4); } out.source[0].hasColors.resize(1); out.source[0].hasColors[0] = true; out.source[0].cols.resize(1); out.source[0].cols[0] = cdf; } else { if (GDALSetRasterColorTable(hTarget, hColorTable) != CE_None) { out.setError("cannot set color table"); GDALClose(hDstDS); return out; } } GDALClose(hDstDS); if (driver != "MEM") { out = SpatRaster(filename, {-1}, {""}, {}); } return out; } SpatRaster SpatRaster::sieveFilter(int threshold, int connections, SpatOptions &opt) { SpatRaster out = geometry(1, true, true, true); if ((connections != 4) && (connections != 8)) { out.setError("connections should be 4 or 8"); return out; } if (threshold < 1) { out.setError("threshold should be > 0"); return out; } std::string filename = opt.get_filename(); std::string driver; if (filename == "") { if (canProcessInMemory(opt)) { driver = "MEM"; } else { filename = tempFile(opt.get_tempdir(), opt.pid, ".tif"); opt.set_filenames({filename}); driver = "GTiff"; } } else { driver = opt.get_filetype(); getGDALdriver(filename, driver); if (driver == "") { setError("cannot guess file type from filename"); return out; } std::string errmsg; if (!can_write(filename, opt.get_overwrite(), errmsg)) { out.setError(errmsg); return out; } } SpatOptions ops(opt); GDALDatasetH hSrcDS, hDstDS; if (!open_gdal(hSrcDS, 0, false, ops)) { out.setError("cannot open input dataset"); return out; } GDALDriverH hDriver = GDALGetDriverByName( driver.c_str() ); if ( hDriver == NULL ) { out.setError("empty driver"); return out; } if (!out.create_gdalDS(hDstDS, filename, driver, true, 0, source[0].has_scale_offset, source[0].scale, source[0].offset, opt)) { out.setError("cannot create new dataset"); GDALClose(hSrcDS); return out; } GDALRasterBandH hSrcBand = GDALGetRasterBand(hSrcDS, 1); GDALRasterBandH hTargetBand = GDALGetRasterBand(hDstDS, 1); if (!GDALSieveFilter(hSrcBand, NULL, hTargetBand, threshold, connections, NULL, NULL, NULL)) { out.setError("sieve failed"); GDALClose(hSrcDS); GDALClose(hDstDS); return out; } GDALClose(hSrcDS); if (driver == "MEM") { if (!out.from_gdalMEM(hDstDS, false, true)) { out.setError("conversion failed (mem)"); GDALClose(hDstDS); return out; } } else { out = SpatRaster(filename, {-1}, {""}, {}); } GDALClose(hDstDS); return out; } /* SpatRaster SpatRaster::fillna(int threshold, int connections, SpatOptions &opt) { CPLErr GDALFillNodata(GDALRasterBandH hTargetBand, GDALRasterBandH hMaskBand, doubledfMaxSearchDist, intbDeprecatedOption, intnSmoothingIterations, char**papszOptions, GDALProgressFuncpfnProgress, void*pProgressArg) */ /* #include SpatRaster SpatRaster::panSharpen(SpatRaster pan, SpatOptions &opt) { SpatRaster out = geometry(); return out; } */ /* bool old_gdal_warper(GDALDatasetH &hSrcDS, GDALDatasetH &hDstDS, std::vector srcbands, std::vector dstbands, std::string method, std::string srccrs, std::string msg, bool verbose, bool threads) { if (srcbands.size() != dstbands.size()) { msg = "number of source bands must match number of dest bands"; return false; } int nbands = srcbands.size(); GDALResampleAlg a = getAlgo(method); // Setup warp options. GDALWarpOptions *psWarpOptions = GDALCreateWarpOptions(); psWarpOptions->hSrcDS = hSrcDS; psWarpOptions->hDstDS = hDstDS; psWarpOptions->eResampleAlg = a; psWarpOptions->nBandCount = nbands; psWarpOptions->panSrcBands = (int *) CPLMalloc(sizeof(int) * nbands ); psWarpOptions->panDstBands = (int *) CPLMalloc(sizeof(int) * nbands ); psWarpOptions->padfSrcNoDataReal = (double *) CPLMalloc(sizeof(double) * nbands ); psWarpOptions->padfDstNoDataReal = (double *) CPLMalloc(sizeof(double) * nbands ); psWarpOptions->padfSrcNoDataImag = (double *) CPLMalloc(sizeof(double) * nbands ); psWarpOptions->padfDstNoDataImag = (double *) CPLMalloc(sizeof(double) * nbands ); GDALRasterBandH hBand; int hasNA; for (int i=0; ipanSrcBands[i] = (int) srcbands[i]+1; psWarpOptions->panDstBands[i] = (int) dstbands[i]+1; hBand = GDALGetRasterBand(hSrcDS, srcbands[i]+1); double naflag = GDALGetRasterNoDataValue(hBand, &hasNA); if (verbose && i == 0) { #ifdef useRcpp std::string hna = hasNA ? "true" : "false"; Rcpp::Rcout << "hasNA : " << hna << std::endl; Rcpp::Rcout << "NA flag : " << naflag << std::endl; #endif } if (hasNA) { psWarpOptions->padfSrcNoDataReal[i] = naflag; psWarpOptions->padfDstNoDataReal[i] = naflag; hBand = GDALGetRasterBand(hDstDS, dstbands[i]+1); GDALSetRasterNoDataValue(hBand, naflag); } else { psWarpOptions->padfSrcNoDataReal[i] = NAN; psWarpOptions->padfDstNoDataReal[i] = NAN; } psWarpOptions->padfSrcNoDataImag[i] = 0; psWarpOptions->padfDstNoDataImag[i] = 0; } //psWarpOptions->pfnProgress = GDALTermProgress; psWarpOptions->papszWarpOptions = CSLSetNameValue( psWarpOptions->papszWarpOptions, "INIT_DEST", "NO_DATA"); psWarpOptions->papszWarpOptions = CSLSetNameValue( psWarpOptions->papszWarpOptions, "WRITE_FLUSH", "YES"); if (threads) { psWarpOptions->papszWarpOptions = CSLSetNameValue( psWarpOptions->papszWarpOptions, "NUM_THREADS", "ALL_CPUS"); } psWarpOptions->pTransformerArg = GDALCreateGenImgProjTransformer( hSrcDS, srccrs.c_str(), hDstDS, GDALGetProjectionRef(hDstDS), FALSE, 0.0, 1 ); psWarpOptions->pfnTransformer = GDALGenImgProjTransform; GDALWarpOperation oOperation; if (oOperation.Initialize( psWarpOptions ) != CE_None) { return false; } oOperation.ChunkAndWarpImage( 0, 0, GDALGetRasterXSize( hDstDS ), GDALGetRasterYSize( hDstDS ) ); GDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg ); GDALDestroyWarpOptions( psWarpOptions ); return true; } */ /* SpatRaster SpatRaster::very_old_warper(SpatRaster x, std::string crs, std::string method, bool mask, SpatOptions &opt) { SpatRaster out = x.geometry(nlyr(), false, false); out.setNames(getNames()); if (method == "near") { out.source[0].hasColors = hasColors(); out.source[0].cols = getColors(); out.source[0].hasCategories = hasCategories(); out.source[0].cats = getCategories(); out.rgb = rgb; out.rgblyrs = rgblyrs; } if (hasTime()) { out.source[0].hasTime = true; out.source[0].timestep = getTimeStep(); out.source[0].time = getTime(); } bool use_crs = crs != ""; std::string filename = opt.get_filename(); if ((!use_crs) & (!hasValues())) { if (filename != "") { out.addWarning("raster has no values, not writing to file"); } return out; } if (!is_valid_warp_method(method)) { out.setError("not a valid warp method"); return out; } lrtrim(crs); std::string errmsg; SpatOptions mopt; if (mask) { mopt = opt; opt = SpatOptions(opt); } filename = opt.get_filename(); std::string srccrs = getSRS("wkt"); if (srccrs == "") { out.setError("input raster CRS not set"); return out; } if (filename == "") { if (!canProcessInMemory(opt) || !out.canProcessInMemory(opt)) { filename = tempFile(opt.get_tempdir(), ".tif"); } } else { if (!can_write(filename, opt.get_overwrite(), errmsg)) { out.setError(errmsg); return out; } } if (opt.names.size() == out.nlyr()) { out.setNames(opt.names); } if (!hasValues()) filename = ""; // for crs case std::string driver = filename == "" ? "MEM" : "GTiff"; GDALDatasetH hSrcDS, hDstDS; size_t ns = nsrc(); int bandstart = 0; for (size_t i=0; i srcbands = source[i].layers; std::vector dstbands(srcbands.size()); std::iota (dstbands.begin(), dstbands.end(), bandstart); bandstart += dstbands.size(); bool success = gdal_warper(hSrcDS, hDstDS, srcbands, dstbands, method, srccrs, errmsg, opt.get_verbose()); GDALClose( hSrcDS ); if (!success) { GDALClose( hDstDS ); out.setError(errmsg); return out; } } if (driver == "MEM") { bool test = out.from_gdalMEM(hDstDS, use_crs, true); GDALClose( hDstDS ); if (!test) { out.setError("cannot do this transformation (warp)"); return out; } } else { std::vector nms = getNames(); for (size_t i=0; i < nlyr(); i++) { GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, i+1); double adfMinMax[2]; bool approx = ncell() > 10e+8; GDALComputeRasterMinMax(hBand, approx, adfMinMax); GDALSetRasterStatistics(hBand, adfMinMax[0], adfMinMax[1], NAN, NAN); GDALSetDescription(hBand, nms[i].c_str()); } GDALClose( hDstDS ); out = SpatRaster(filename, {-1}, {""}); } if (mask) { SpatVector v = dense_extent(); v = v.project(out.getSRS("wkt")); out = out.mask(v, false, NAN, true, mopt); } return out; } */ terra/src/crs.h0000644000175000017500000000107514201035750013250 0ustar nileshnilesh//#ifdef useGDAL #include "ogr_spatialref.h" SpatMessages transform_coordinates(std::vector &x, std::vector &y, std::string fromCRS, std::string toCRS); bool wkt_from_spatial_reference(const OGRSpatialReference *srs, std::string &wkt, std::string &msg); bool prj_from_spatial_reference(const OGRSpatialReference *srs, std::string &prj, std::string &msg); //std::vector srefs_from_string(std::string input); bool wkt_from_string(std::string input, std::string& wkt, std::string& msg); bool is_ogr_error(OGRErr err, std::string &msg); //#endif terra/src/graticule.cpp0000644000175000017500000000032014201035750014763 0ustar nileshnilesh//#include "spatVector.h" //SpatVector graticule(SpatExtent ext, std::string crs, size_t nx, size_t ny) { //srs s; //s.set(crs); // get xrange in lon // find pretty breaks // get yrange in lat //} terra/src/spatTime.cpp0000644000175000017500000002036114201035750014601 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include #include #include //#include #include "string_utils.h" typedef long long SpatTime_t; bool isleap(const long &year) { return (year % 4 == 0) && ((year % 400 == 0) || (year % 100 != 0 )); } SpatTime_t yeartime(const long &year) { // seconds per year // 365 * 24 * 3600 = 31536000 return isleap(year) ? 31622400 : 31536000; } SpatTime_t get_time(long year, unsigned month, unsigned day, unsigned hr, unsigned min, unsigned sec) { static const unsigned mdays[2][12] = { {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335} }; if (month > 12) { year += month / 12; month = ((month-1) % 12) + 1; } // the first day does not count, we start at 1970-01-01 // 24 * 3600 = 86400 SpatTime_t time = -86400; if (year < 1970) { for (long y = year; y < 1970; y++){ time -= yeartime(y); } } else { for (long y = 1970; y < year; y++) { time += yeartime(y); } } time += (mdays[isleap(year)][month-1] + day) * 86400; time += (hr * 3600) + (min * 60) + sec; return time; } SpatTime_t get_time_str(std::vector s) { std::vector d(6, 0); for (size_t i=0; i get_date(SpatTime_t x) { // seconds per month, shifted one month static const unsigned secdays[2][13] = { {0, 2678400, 5097600, 7776000, 10368000, 13046400, 15638400, 18316800, 20995200, 23587200, 26265600, 28857600, 31536000}, {0, 2678400, 5184000, 7862400, 10454400, 13132800, 15724800, 18403200, 21081600, 23673600, 26352000, 28944000, 31622400} }; // the first day does not count, we start at 1970-01-01 int year = 1970; if (x < 0) { while (x < 0) { year--; x += yeartime(year); } } else if (x > 0) { while (x > 0) { x -= yeartime(year); year++; } year--; x += yeartime(year); } int month; for (month=1; month<13; month++) { if (x < (secdays[isleap(year)][month])) { break; } } x -= secdays[isleap(year)][month-1]; int day = x / 86400 + 1; x = x % 86400; int hour = x / 3600; x = x % 3600; int min = x / 60; int sec = x % 60; std::vector out= {year, month, day, hour, min, sec}; return out; } std::vector splitstr(std::string s, std::string delimiter){ std::vector out; size_t pos = 0; while ((pos = s.find(delimiter)) != std::string::npos) { out.push_back(s.substr(0, pos)); s.erase(0, pos + delimiter.length()); } out.push_back(s.substr(0, pos)); return out; } void replace_one_char(std::string& s, char from, char to) { for (size_t i = 0; i < s.size(); i++) { if (s[i] == from) { s[i] = to; } } } std::vector getymd(std::string s) { // s = std::regex_replace(s, std::regex("T"), " "); replace_one_char(s, 'T', ' '); size_t ncolon = std::count(s.begin(), s.end(), ':'); std::vector x; std::vector y; if (ncolon > 0) { x = splitstr(s, " "); s = x[0]; if (x.size() > 1) { std::string f = s; f.erase(std::remove(f.begin(), f.end(), 'Z'), f.end()); x[1] = f; //x[1] = std::regex_replace(s, std::regex("Z"), ""); y = splitstr(x[1], ":"); } } size_t ndash = std::count(s.begin(), s.end(), '-'); if (ndash == 2) { x = splitstr(s, "-"); } x.insert( x.end(), y.begin(), y.end() ); std::vector out(x.size()); for (size_t i=0; i ss; size_t ncolon = std::count(s.begin(), s.end(), ':'); if (ncolon > 0) { ss = splitstr(s, " "); s = ss[0]; } size_t ndash = std::count(s.begin(), s.end(), '-'); SpatTime_t time = 0; if (ndash == 2) { ss = splitstr(s, "-"); } else { return time; } time = get_time(std::stoi(ss[0]), std::stoi(ss[1]), std::stoi(ss[2]), 0, 0, 0); // } else { // time = get_time_noleap(std::stoi(ss[0]), std::stoi(ss[1]), std::stoi(ss[2])); // } return time; } SpatTime_t time_from_hour(int syear, int smonth, int sday, double nhours) { SpatTime_t time = get_time(syear, smonth, sday, 0, 0, 0); time += nhours * 3600; return time; } void hours_to_time(std::vector &time, std::string origin) { std::vector ymd = getymd(origin); SpatTime_t otime = get_time(ymd[0], ymd[1], ymd[2], 0, 0, 0); for (SpatTime_t &d : time) d = otime + d * 3600; } SpatTime_t time_from_day(int syear, int smonth, int sday, double ndays) { SpatTime_t time = get_time(syear, smonth, sday, 0, 0, 0); time += ndays * 86400; return time; } SpatTime_t time_from_day_noleap(int syear, int smonth, int sday, double ndays) { static const int md[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; int year = ndays / 365; //int doy = ndays % 365; int doy = ndays - (year * 365); int month; for (month=1; month<13; month++) { if (doy < md[month]) { break; } } month--; int day = doy - md[month]; SpatTime_t time = get_time(year+syear, month+smonth, day+sday, 0, 0, 0); return time; } SpatTime_t time_from_day_360(int syear, int smonth, int sday, double ndays) { static const int md[13] = {0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, 360 }; int year = ndays / 360; //int doy = ndays % 360; int doy = ndays - (year * 360); int month; for (month=1; month<13; month++) { if (doy < md[month]) { break; } } month--; int day = doy - md[month]; SpatTime_t time = get_time(year+syear, month+smonth, day+sday, 0, 0, 0); return time; } SpatTime_t parse_time(std::string x) { lrtrim(x); std::vector s = strsplit(x, " "); std::vector time = strsplit(s[0], "-"); if (time.size() == 1) { return stoi(time[0]); } else if (time.size() != 3) { return 0; } if (s.size() > 1) { std::vector secs = strsplit(s[1], ":"); if (secs.size() == 3) { time.insert(time.end(), secs.begin(), secs.end()); } } return get_time_str(time); } /* SpatTime_t get_time_noleap(long year, unsigned month, unsigned day=15, unsigned hr=0, unsigned min=0, unsigned sec=0) { static const unsigned mdays[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; // the first day does not count, we start at 1970-01-01 // 24 * 3600 = 86400 SpatTime_t time = -86400; if (year < 1970) { for (long y = year; y < 1970; y++){ time -= 31536000; } } else { for (long y = 1970; y < year; y++) { time += 31536000; } } time += (mdays[month-1] + day) * 86400; time += (hr * 3600) + (min * 60) + sec; return time; } SpatTime_t get_time_noleap_day(long long day, SpatTime_t offset=0) { static const int cumdays[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; int year = day / 365; int doy = day % 365; int month; for (month=1; month<13; month++) { if (doy < cumdays[month]) { break; } } day = day - cumdays[month-1]; SpatTime_t time = get_time(year, month, day, 0, 0, 0); return (offset + time); } SpatTime_t get_time360(long year, unsigned month, unsigned day=15, unsigned hr=0, unsigned min=0, unsigned sec=0) { static const unsigned mdays[12] = {0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330}; // the first day does not count, we start at 1970-01-01 // 24 * 3600 = 86400 SpatTime_t time = -86400; if (year < 1970) { for (long y = year; y < 1970; y++){ time -= 31104000; //360 * 86400; } } else { for (long y = 1970; y < year; y++) { time += 31104000; } } time += (mdays[month-1] + day) * 86400; time += (hr * 3600) + (min * 60) + sec; return time; } */ terra/src/progress_monitor_interruptable.hpp0000644000175000017500000001124314201035750021372 0ustar nileshnilesh/* * interruptable_progress_monitor.hpp * * A class that monitors the progress of computations: * - can display a progress bar * - can handle user interrupt (R user level) or programmatic abort * - can be used in OpenMP loops * * Author: karl.forner@gmail.com * */ #ifndef _RcppProgress_INTERRUPTABLE_PROGRESS_MONITOR_HPP #define _RcppProgress_INTERRUPTABLE_PROGRESS_MONITOR_HPP #include "progress_interrupts.hpp" #include "progress_bar.hpp" //#include "fetch_raw_gwas_bar.hpp" #ifdef _OPENMP #include #endif class InterruptableProgressMonitor { public: // ====== LIFECYCLE ===== /** * Main constructor * * @param max the expected number of tasks to perform * @param display_progress whether to display a progress bar in the console * @param pb the ProgressBar instance to use */ InterruptableProgressMonitor( unsigned long max, bool display_progress, ProgressBar& pb ) : _progress_bar(pb) { reset(max, display_progress); if (is_display_on()) { _progress_bar.display(); } } ~InterruptableProgressMonitor() { if (is_display_on() && !is_aborted()) _progress_bar.end_display(); } public: // ===== ACCESSORS/SETTERS ===== void set_display_status(bool on) { _display_progress = on; } bool is_display_on() const { return _display_progress; } unsigned long get_max() const { return _max; } bool is_aborted() const { return _abort; } public: // ===== PBLIC MAIN INTERFACE ===== /** * increment the current progress. * * Iff called by the master thread, it will also update the display if needed * * @param amount the number of newly performed tasks to report * * @return false iff the computation is aborted */ bool increment(unsigned long amount=1) { if ( is_aborted() ) return false; return is_master() ? update_master(_current + amount) : atomic_increment(amount); } /** * set the current progress indicator * * Iff called by the master thread, it will also update the display if needed * * @param current the total number of performed tasks so far (by all threads) * * @return false iff the computation is aborted */ bool update(unsigned long current) { if ( is_aborted() ) return false; return is_master() ? update_master(current) : atomic_update(current); } /** * check that the no interruption has been requested and return the current status * * Iff called by the master thread, it will check for R-user level interruption. * * @return true iff the computation is aborted */ bool check_abort() { if ( is_aborted() ) return true; if ( is_master() ) { check_user_interrupt_master(); } return is_aborted(); } /** * request computation abortion */ void abort() { #ifdef _OPENMP #pragma omp critical #endif _abort = true; } /** * return true iff the thread is the master. * In case of non-OpenMP loop, always return true */ bool is_master() const { #ifdef _OPENMP return omp_get_thread_num() == 0; #else return true; #endif } public: // ===== methods for MASTER thread ===== /** * set the current progress indicator and update the progress bar display if needed. * * * @param current the total number of performed tasks * * @return false iff the computation is aborted */ bool update_master(unsigned long current) { _current = current; if (is_display_on()) _progress_bar.update(progress(current)); return ! is_aborted(); } void check_user_interrupt_master() { if ( !is_aborted() && checkInterrupt() ) { abort(); } } public: // ===== methods for non-MASTER threads ===== bool atomic_increment(unsigned long amount=1) { #ifdef _OPENMP #pragma omp atomic #endif _current+=amount; return ! is_aborted(); } bool atomic_update(unsigned long current) { #ifdef _OPENMP #pragma omp critical #endif _current=current; return ! is_aborted(); } protected: // ==== other instance methods ===== // convert current value to [0-1] progress double progress(unsigned long current) { return double(current) / double(_max); } /** * reset the monitor. * * Currently not really useful * * @param max the expected number of tasks to perform * @param display_progress whether to display a progress bar in the console * */ void reset(unsigned long max = 1, bool display_progress = true) { _max = max; if ( _max <= 0 ) _max = 1; _current = 0; _display_progress = display_progress; _abort = false; } private: // ===== INSTANCE VARIABLES ==== ProgressBar& _progress_bar; unsigned long _max; // the nb of tasks to perform unsigned long _current; // the current nb of tasks performed bool _abort; // whether the process should abort bool _display_progress; // whether to display the progress bar }; #endif terra/src/spatVector.cpp0000644000175000017500000006213314201035750015150 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include "spatVector.h" #include #include "math_utils.h" #include "vecmath.h" #ifdef useGDAL #include "crs.h" #endif SpatHole::SpatHole() {} SpatHole::SpatHole(std::vector X, std::vector Y) { x = X; y = Y; extent.xmin = *std::min_element(X.begin(), X.end()); extent.xmax = *std::max_element(X.begin(), X.end()); extent.ymin = *std::min_element(Y.begin(), Y.end()); extent.ymax = *std::max_element(Y.begin(), Y.end()); } bool SpatPart::addHole(std::vector X, std::vector Y) { SpatHole h(X, Y); holes.push_back(h); // check if inside pol? return true; } bool SpatPart::addHole(SpatHole h) { holes.push_back(h); // check if inside pol? return true; } SpatPart::SpatPart() {} SpatPart::SpatPart(double X, double Y) { x.push_back(X); y.push_back(Y); extent.xmin = X; extent.xmax = X; extent.ymin = Y; extent.ymax = Y; } SpatPart::SpatPart(std::vector X, std::vector Y) { x = X; y = Y; extent.xmin = *std::min_element(X.begin(), X.end()); extent.xmax = *std::max_element(X.begin(), X.end()); extent.ymin = *std::min_element(Y.begin(), Y.end()); extent.ymax = *std::max_element(Y.begin(), Y.end()); } SpatGeom::SpatGeom() {} SpatGeom::SpatGeom(SpatPart p) { parts.push_back(p); extent = p.extent; } SpatGeom::SpatGeom(SpatGeomType g) { gtype = g; } bool SpatGeom::unite(SpatGeom g) { if (parts.size() == 0) { parts = g.parts; extent = g.extent; } else { parts.insert(parts.end(), g.parts.begin(), g.parts.end()); extent.unite(g.extent); } return true; } bool SpatGeom::addPart(SpatPart p) { parts.push_back(p); if (parts.size() > 1) { extent.unite(p.extent); } else { extent = p.extent; } return true; } bool SpatGeom::addHole(SpatHole h) { long i = parts.size()-1; if (i > -1) { parts[i].addHole(h); return true; } else { return false; } } bool SpatGeom::setPart(SpatPart p, unsigned i) { parts[i] = p; if (parts.size() > 1) { extent.unite(p.extent); } else { extent = p.extent; } return true; } bool SpatGeom::reSetPart(SpatPart p) { parts.resize(1); parts[0] = p; extent = p.extent; return true; } SpatPart SpatGeom::getPart(unsigned i) { return parts[i]; } size_t SpatGeom::ncoords() { size_t ncrds = 0; size_t np = parts.size(); for (size_t j=0; j> SpatGeom::coordinates() { std::vector> out(2); size_t np = size(); size_t ncrds = ncoords(); out[0].reserve(ncrds); out[1].reserve(ncrds); for (size_t j=0; j x = { e.xmin, e.xmin, e.xmax, e.xmax, e.xmin }; std::vector y = { e.ymin, e.ymax, e.ymax, e.ymin, e.ymin }; SpatPart p(x, y); SpatGeom g(p); g.gtype = polygons; setGeom(g); setSRS( {crs}); } SpatVector::SpatVector(std::vector x, std::vector y, SpatGeomType g, std::string crs) { if (x.size() == 0) return; if (g == points) { SpatPart p(x[0], y[0]); SpatGeom geom(p); geom.gtype = g; setGeom(geom); for (size_t i=1; i SpatVector::getDv(unsigned i) { return df.getD(i); } std::vector SpatVector::getIv(unsigned i){ return df.getI(i); } std::vector SpatVector::getSv(unsigned i){ return df.getS(i); } std::vector SpatVector::getItype(){ return df.itype; } std::vector SpatVector::getIplace(){ return df.iplace; } std::vector SpatVector::get_names(){ return df.get_names(); } void SpatVector::set_names(std::vector s){ df.set_names(s); } unsigned SpatVector::ncol() { return df.ncol(); } unsigned SpatVector::nrow() { return geoms.size(); } size_t SpatVector::size() { return geoms.size(); } bool SpatVector::is_lonlat() { return srs.is_lonlat(); } bool SpatVector::could_be_lonlat() { if (srs.is_lonlat()) return true; SpatExtent e = getExtent(); return srs.could_be_lonlat(e); } SpatExtent SpatVector::getExtent(){ return extent; } /* void SpatVector::setPRJ(std::string PRJ){ crs[0] = PRJ; } std::string SpatVector::getPRJ(){ return crs[0]; } */ std::string SpatVector::type(){ if (size() == 0) { return "none"; } else if (geoms[0].gtype == points) { return "points"; } else if (geoms[0].gtype == lines) { return "lines"; } else if (geoms[0].gtype == polygons) { return "polygons"; } else { return("unknown"); } } SpatGeom SpatVector::getGeom(unsigned i) { return geoms[i]; } bool SpatVector::addGeom(SpatGeom p) { geoms.push_back(p); if (geoms.size() > 1) { extent.unite(p.extent); } else { extent = p.extent; } return true; } bool SpatVector::setGeom(SpatGeom p) { geoms.resize(1); geoms[0] = p; extent = p.extent; return true; } void SpatVector::computeExtent() { if (geoms.size() == 0) return; extent = geoms[0].extent; for (size_t i=1; i> SpatVector::coordinates() { std::vector> out(2); for (size_t i=0; i < size(); i++) { SpatGeom g = getGeom(i); for (size_t j=0; j < g.size(); j++) { SpatPart p = g.getPart(j); for (size_t q=0; q < p.x.size(); q++) { out[0].push_back( p.x[q] ); out[1].push_back( p.y[q] ); } if (p.hasHoles()) { for (size_t k=0; k < p.nHoles(); k++) { SpatHole h = p.getHole(k); for (size_t q=0; q < h.x.size(); q++) { out[0].push_back( h.x[q] ); out[1].push_back( h.y[q] ); } } } } } return out; } */ size_t SpatVector::ncoords() { size_t ncrds = 0; size_t ng = geoms.size(); for (size_t i=0; i> SpatVector::coordinates() { std::vector> out(2); size_t ncrds = ncoords(); out[0].reserve(ncrds); out[1].reserve(ncrds); size_t ng = size(); for (size_t i=0; i> SpatVector::getGeometry() { unsigned n = nxy(); std::vector> out(5); for (size_t i=0; i>out.size(); i++) { out[i].reserve(n); } for (size_t i=0; i < size(); i++) { SpatGeom g = getGeom(i); if (g.size() == 0) { // empty out[0].push_back(i+1); out[1].push_back(1); out[2].push_back(NAN); out[3].push_back(NAN); out[4].push_back(0); } for (size_t j=0; j < g.size(); j++) { SpatPart p = g.getPart(j); for (size_t q=0; q < p.x.size(); q++) { out[0].push_back(i+1); out[1].push_back(j+1); out[2].push_back(p.x[q]); out[3].push_back(p.y[q]); out[4].push_back(0); } if (p.hasHoles()) { for (size_t k=0; k < p.nHoles(); k++) { SpatHole h = p.getHole(k); for (size_t q=0; q < h.x.size(); q++) { out[0].push_back(i+1); out[1].push_back(j+1); out[2].push_back(h.x[q]); out[3].push_back(h.y[q]); out[4].push_back(k+1); } } } } } return out; } std::string nice_string(const double &x) { std::string s = std::to_string(x); s.erase(s.find_last_not_of('0') + 1, std::string::npos); s.erase(s.find_last_not_of('.') + 1, std::string::npos); return s; } std::vector SpatVector::getGeometryWKT() { std::vector out(size()); std::string wkt; for (size_t i=0; i < size(); i++) { SpatGeom g = getGeom(i); size_t n = g.size(); if (g.gtype == points) { if (n > 1) { wkt = "MULTIPOINT "; } else { wkt = "POINT "; } } else if (g.gtype == lines) { if (n > 1) { wkt = "MULTILINESTRING "; } else { wkt = "LINESTRING "; } } else if (g.gtype == polygons) { if (n > 1) { wkt = "MULTIPOLYGON "; } else { wkt = "POLYGON "; } } if (n == 0) { wkt += "EMPTY"; out[i] = wkt; continue; } if ((g.gtype == polygons) | (n > 1)) { wkt += "("; } for (size_t j=0; j < n; j++) { SpatPart p = g.getPart(j); if (j>0) wkt += ","; if ((g.gtype == polygons) & (n > 1)) { wkt += "("; } wkt += "(" + nice_string(p.x[0]) + " " + nice_string(p.y[0]); for (size_t q=1; q < p.x.size(); q++) { wkt += ", " + nice_string(p.x[q]) + " " + nice_string(p.y[q]); } wkt += ")"; if (p.hasHoles()) { for (size_t k=0; k < p.nHoles(); k++) { SpatHole h = p.getHole(k); wkt += ",(" + nice_string(h.x[0]) + " " + nice_string(h.y[0]); for (size_t q=1; q < h.x.size(); q++) { wkt += ", " + nice_string(h.x[q]) + " " + nice_string(h.y[q]); } wkt += ")"; } } if ((g.gtype == polygons) & (n > 1)) { wkt += ")"; } } if ((g.gtype == polygons) | (n > 1)) { wkt += ")"; } out[i] = wkt; } return out; } SpatGeomType SpatVector::getGType(std::string &type) { if (type == "points") { return points; } else if (type == "lines") { return lines; } else if (type == "polygons") { return polygons; } else { return unknown; } } void SpatVector::setGeometry(std::string type, std::vector gid, std::vector part, std::vector x, std::vector y, std::vector hole) { // it is assumed that values are sorted by gid, part, hole unsigned lastgeom = gid[0]; unsigned lastpart = part[0]; unsigned lasthole = hole[0]; bool isHole = lasthole > 0; std::vector X, Y; SpatGeom g; g.gtype = getGType(type); for (size_t i=0; i 0) { if (g.gtype == polygons) { if ((X[0] != X[X.size()-1]) || (Y[0] != Y[Y.size()-1])) { X.push_back(X[0]); Y.push_back(Y[0]); } if (isHole) { SpatHole h(X, Y); g.addHole(h); } else { SpatPart p(X, Y); g.addPart(p); } } else { SpatPart p(X, Y); g.addPart(p); } } else { SpatPart p(NAN, NAN); g.addPart(p); } lastpart = part[i]; lasthole = hole[i]; isHole = lasthole > 0; X.resize(0); Y.resize(0); if (lastgeom != gid[i]) { addGeom(g); g.parts.resize(0); lastgeom = gid[i]; } } if (!(std::isnan(x[i]) || std::isnan(y[i]))) { X.push_back(x[i]); Y.push_back(y[i]); } } if (X.size() > 0) { if (g.gtype == polygons) { if ((X[0] != X[X.size()-1]) || (Y[0] != Y[Y.size()-1])) { X.push_back(X[0]); Y.push_back(Y[0]); } if (isHole) { SpatHole h(X, Y); g.addHole(h); } else { SpatPart p(X, Y); g.addPart(p); } } else { SpatPart p(X, Y); g.addPart(p); } } else { SpatPart p(NAN, NAN); g.addPart(p); } addGeom(g); } /* void SpatVector::setPointsGeometry(std::vector &x, std::vector &y) { size_t n = x.size(); if (n == 0) return; reserve(n); SpatGeom g; g.gtype = points; SpatPart p(x[0],y[0]); g.addPart(p);; for (size_t i=0; i &x, std::vector &y) { size_t n = x.size(); //reserve(n) if (n == 0) return; SpatGeom g; g.gtype = points; SpatPart p(x[0],y[0]); g.addPart(p); geoms.resize(n, g); for (size_t i=1; i geo, std::string crs) { if (x.nrow() == 0) return; if ((x.itype[geo[0]] != 0) || (x.itype[geo[1]] != 0)) { setError("coordinates must be numeric"); return; } if (geo[0] == geo[1]) { setError("x and y coordinates are the same variable"); return; } setPointsGeometry(x.dv[x.iplace[geo[0]]], x.dv[x.iplace[geo[1]]]); setSRS( {crs}); if (geo[0] > geo[1]) { x.remove_column(geo[0]); x.remove_column(geo[1]); } else { x.remove_column(geo[1]); x.remove_column(geo[0]); } df = x; } SpatVector SpatVector::subset_rows(std::vector range) { SpatVector out; int n = nrow(); std::vector r; for (size_t i=0; i= 0) & (range[i] < n)) { r.push_back(range[i]); } } for (size_t i=0; i < r.size(); i++) { out.addGeom( geoms[r[i]] ); } out.srs = srs; out.df = df.subset_rows(r); return out; } SpatVector SpatVector::subset_rows(std::vector range) { SpatVector out; unsigned n = nrow(); std::vector r; for (size_t i=0; i range(1, i); SpatVector out = subset_rows(range); return out; } SpatVector SpatVector::remove_rows(std::vector range) { std::sort(range.begin(), range.end()); range.erase(std::unique(range.begin(), range.end()), range.end()); std::reverse(range.begin(), range.end()); std::vector id(size()); std::iota(id.begin(), id.end(), 0); unsigned n = size(); for (size_t i=0; i range) { int nc = ncol(); std::vector valid; valid.reserve(range.size()); for (size_t i=0; i= 0) & (range[i] < nc)) { valid.push_back(range[i]); } } SpatVector out = *this; out.df = df.subset_cols(valid); return out; } SpatVector SpatVector::subset_cols(int i) { if (i < 0) { SpatVector out; out.geoms = geoms; out.srs = srs; return out; } std::vector range = {i}; return subset_cols(range); } SpatVector SpatVector::append(SpatVector x, bool ingnorecrs) { if (size() == 0) return x; if (x.size() == 0) return *this; SpatVector out; if (type() != x.type()) { out.setError("geom types do not match"); return out; } if (!(ingnorecrs)) { if (!srs.is_same(x.srs, true)) { out.setError("append: crs does not match"); return out; } } out = *this; for (size_t i=0; i 0) && (x.df.nrow() > 0)) { out.df.rbind(x.df); return out; } if (x.df.nrow() == 0) { out.df.add_rows(x.size()); } else { std::vector i; out.df = x.df.subset_rows(i); out.df.add_rows(size()); out.df.rbind(x.df); } return out; } SpatVector SpatVector::cbind(SpatDataFrame d) { if (nrow() != d.nrow()) { SpatVector out; out.setError("nrow does not match"); return out; } SpatVector out = *this; if (!out.df.cbind(d)) { out.setError("cbind failed"); } return out; } SpatVector SpatVector::as_points(bool multi, bool skiplast) { if (geoms[0].gtype == points) { SpatVector v = *this; v.addWarning("returning a copy"); return v; } SpatVector v = *this; if (geoms[0].gtype == lines) { for (size_t i=0; i < v.geoms.size(); i++) { SpatGeom g; g.gtype = points; for (size_t j=0; j 0) { size_t n = p.size(); for (size_t k=0; k 0) { size_t n = p.size() - skip; for (size_t k=0; k x, y; x.reserve(size()); y.reserve(size()); for (size_t i=0; i=0; i--) { if (v.geoms[i].parts.size() > 1) { for (size_t j=1; j &x, int digits) { for (double& d : x) d = roundn(d, digits); } void remove_duplicates(std::vector &x, std::vector &y, int digits) { if (digits > -1) { vecround(x, digits); vecround(y, digits); } size_t start = x.size() - 1; for (size_t i=start; i>0; i--) { if ((x[i] == x[i-1]) && (y[i] == y[i-1])) { x.erase(x.begin()+i); y.erase(y.begin()+i); } } } void SpatGeom::remove_duplicate_nodes(int digits) { size_t start = parts.size()-1; for (size_t i=start; i>0; i--) { remove_duplicates(parts[i].x, parts[i].y, digits); if (parts[i].x.size() < 4) { parts.erase(parts.begin()+i); continue; } if (parts[i].hasHoles()) { for (size_t j=0; j < parts[i].nHoles(); j++) { remove_duplicates(parts[i].holes[j].x, parts[i].holes[j].y, digits); if (parts[i].holes[j].x.size() < 4) { parts[i].holes.erase(parts[i].holes.begin()+j); } } } } } SpatVector SpatVector::remove_duplicate_nodes(int digits) { SpatVector v = *this; if (geoms[0].gtype == points) { v.addWarning("returning a copy"); return v; } for (size_t i=0; i 0) && (v[i].df.nrow() > 0)) { out.df.rbind(v[i].df); continue; } if (v[i].df.nrow() == 0) { out.df.add_rows(v[i].size()); } else { std::vector r0; out.df = v[i].df.subset_rows(r0); out.df.add_rows(out.size()); out.df.rbind(v[i].df); } } return out; } SpatVector SpatVector::round(int digits) { SpatVector out = *this; size_t ng = out.size(); for (size_t i=0; i. #include "spatRaster.h" #include "vecmath.h" std::vector rcValue(std::vector &d, const int& nrow, const int& ncol, const unsigned& nlyr, const int& row, const int& col) { std::vector out(nlyr, NAN); if ((row < 0) || (row > (nrow -1)) || (col < 0) || (col > (ncol-1))) { return out; } else { unsigned nc = nrow * ncol; unsigned cell = row * ncol + col; for (size_t i=0; i SpatRaster::focal_values(std::vector w, double fillvalue, int_64 row, int_64 nrows, SpatOptions &ops) { if (nlyr() > 1) { std::vector lyr = {0}; SpatRaster s = subset(lyr, ops); s.focal_values(w, fillvalue, row, nrows, ops); } if ((w[0] % 2 == 0) || (w[1] % 2 == 0)) { setError("weights matrix must have uneven sides"); std::vector d; return(d); } const bool global = is_global_lonlat(); int_64 nr = nrow(); nrows = std::min(nrows, nr - row + 1); int_64 nc = ncol(); int_64 wr = w[0] / 2; int_64 wc = w[1] / 2; //may be unexptected //wr = std::min(wr, nr-1); //wc = std::min(wc, nc-1); int_64 startrow = row-wr; startrow = startrow < 0 ? 0 : startrow; int_64 startoff = row-startrow; nrows = nrows < 1 ? 1 : nrows; int_64 readnrows = nrows+startoff+wr; int_64 endoff = wr; if ((startrow+readnrows) > nr ) { readnrows = nr-startrow; endoff = readnrows - (nrows+startoff); } // ?? //wr = std::min(wr, std::max((int_64)1, nrows-1)); size_t n = nrows * nc * w[0] * w[1]; int_64 nrmax = nrows + startoff + endoff - 1; //int nrmax = d.size() / ncol - 1; size_t f = 0; std::vector d; readValues(d, startrow, readnrows, 0, nc); std::vector out(n, fillvalue); //Rcpp::Rcout << "sr " << startrow << " so " << startoff << " rnr " << readnrows << " wr " << wr << " wc " << wc << " nrows " << nrows << std::endl; for (int_64 r=0; r < nrows; r++) { for (int_64 c=0; c < nc; c++) { for (int_64 i = -wr; i <= wr; i++) { int_64 row = r+startoff+i; if ((row < 0) || (row > nrmax)) { f += w[1]; } else { size_t bcell = row * nc; for (int_64 j = -wc; j <= wc; j++) { int_64 col = c + j; if ((col >= 0) && (col < nc)) { size_t idx = bcell+col; out[f] = d[idx]; } else if (global) { if (col < 0) { col = nc + col; } else if (col >= nc) { col = col - nc; } size_t idx = bcell+col; out[f] = d[idx]; } f++; } } } } } return out; } void focal_win_fun(const std::vector &d, std::vector &out, int nc, int srow, int nr, std::vector window, int wnr, int wnc, double fill, bool narm, bool naonly, bool naomit, bool expand, bool global, std::function&, bool)> fun) { out.resize(nc * nr); int hwc = wnc / 2; int hwr = wnr / 2; std::vector winNA(window.size(), false); for (size_t i=0; i v; v.reserve(wnr * wnc); for (int rr=0; rr nc1 ? col - nc : col; v.push_back(d[nc*row + col] * window[wi]); } else if (expand) { col = col < 0 ? 0 : col; col = col > nc1 ? nc1 : col; v.push_back(d[nc*row + col] * window[wi]); } else { if (col >= 0 && col < nc) { v.push_back(d[nc*row + col] * window[wi]); } else { v.push_back(fill * window[wi]); } } } } out[cell] = fun(v, narm); } } } void focal_win_sum(const std::vector &d, std::vector &out, int nc, int srow, int nr, std::vector window, int wnr, int wnc, double fill, bool narm, bool naonly, bool naomit, bool expand, bool global) { out.resize(nc*nr, NAN); int hwc = wnc / 2; int hwr = wnr / 2; bool nafill = std::isnan(fill); bool dofill = !(narm && nafill); std::vector winNA(window.size(), false); for (size_t i=0; i nc1 ? col - nc : col; if (narm) { if (!std::isnan(d[nc * row + col])) { value += d[nc*row + col] * window[wi]; found = true; } } else { value += d[nc*row + col] * window[wi]; } } else if (expand) { col = col < 0 ? 0 : col; col = col > nc1 ? nc1 : col; if (narm) { if (!std::isnan(d[nc * row + col])) { value += d[nc*row + col] * window[wi]; found = true; } } else { value += d[nc*row + col] * window[wi]; } } else { if (col >= 0 && col < nc) { if (narm) { if (!std::isnan(d[nc*row + col])) { value += d[nc*row + col] * window[wi]; found = true; } } else { value += d[nc*row + col] * window[wi]; } } else if (dofill) { value += fill * window[wi]; } } } } if (narm) { if (found) { out[cell] = value; } } else { out[cell] = value; } } } } void focal_win_mean(const std::vector &d, std::vector &out, int nc, int srow, int nr, std::vector window, int wnr, int wnc, double fill, bool narm, bool naonly, bool naomit, bool expand, bool global) { out.resize(nc*nr, NAN); int hwc = wnc / 2; int hwr = wnr / 2; bool nafill = std::isnan(fill); bool dofill = !(narm && nafill); std::vector winNA(window.size(), false); double winsum = 0; std::vector poswin = window; for (size_t i=0; i nc1 ? col - nc : col; if (narm) { if (!std::isnan(d[nc * row + col])) { value += d[nc * row + col] * window[wi]; winsum += poswin[wi]; } } else { value += d[nc * row + col] * window[wi]; } } else if (expand) { col = col < 0 ? 0 : col; col = col > nc1 ? nc1 : col; if (narm) { if (!std::isnan(d[nc * row + col])) { value += d[nc * row + col] * window[wi]; winsum += poswin[wi]; } } else { value += d[nc * row + col] * window[wi]; } } else { if (col >= 0 && col < nc) { if (narm) { if (!std::isnan(d[nc * row + col])) { value += d[nc * row + col] * window[wi]; winsum += poswin[wi]; } } else { value += d[nc * row + col] * window[wi]; } } else if (dofill) { value += fill; if (narm) { winsum += poswin[wi]; } } } } } if (winsum > 0) { out[cell] = value / winsum; } } } } SpatRaster SpatRaster::focal(std::vector w, std::vector m, double fillvalue, bool narm, bool naonly, bool naomit, std::string fun, bool expand, SpatOptions &opt) { SpatRaster out = geometry(); bool global = is_global_lonlat(); size_t nl = nlyr(); if (!source[0].hasValues) { return(out); } if (w.size() != 2) { out.setError("size of w is not 1 or 2"); return out; } if ((w[0] % 2) == 0 || (w[1] % 2) == 0) { out.setError("w must be odd sized"); return out; } unsigned ww = w[0] * w[1]; if (ww < 3) { out.setError("not a meanigful window"); return out; } if (ww != m.size()) { out.setError("weights matrix size does not match prod(w)"); return out; } size_t nc = ncol(); size_t nr = nrow(); if (w[0] > (nr*2)) { out.setError("nrow(w) > 2 * nrow(x)"); return out; } if (w[1] > (nc*2)) { out.setError("ncol(w) > 2 * ncol(x)"); return out; } if (!readStart()) { out.setError(getError()); return(out); } opt.ncopies += 2; opt.minrows = w[0] > nr ? nr : w[0]; if (!out.writeStart(opt)) { readStop(); return out; } size_t hw0 = w[0]/2; size_t dhw0 = hw0 * 2; //size_t fsz = hw0*nc; size_t fsz2 = dhw0*nc; bool dofun = false; std::function&, bool)> fFun; if ((fun != "mean") && (fun != "sum")) { if (!haveFun(fun)) { out.setError("unknown function argument"); return out; } fFun = getFun(fun); dofun = true; } std::vector fill; for (size_t i = 0; i < out.bs.n; i++) { unsigned rstart, roff; unsigned rnrows = out.bs.nrows[i]; if (i == 0) { rstart = 0; roff = dhw0; if (i != (out.bs.n-1)) { rnrows += hw0; } } else { rstart = out.bs.row[i] + hw0; roff = hw0; if (i == (out.bs.n-1)) { rnrows -= hw0; } } std::vector vout, voutcomb; std::vector vin, vincomb; size_t off=0; if (nl > 1) { readValues(vincomb, rstart, rnrows, 0, nc); off = nc * out.bs.nrows[i]; voutcomb.reserve(vincomb.size()); } else { readValues(vin, rstart, rnrows, 0, nc); } for (size_t lyr=0; lyr 1) { size_t lyroff = lyr * off; vin = {vincomb.begin() + lyroff, vincomb.begin() + lyroff + off}; } if (i==0) { if (expand) { fill = {vin.begin(), vin.begin()+nc}; for (size_t i=1; i 1) { voutcomb.insert(voutcomb.end(), vout.begin(), vout.end()); } } if (nl > 1) { if (!out.writeBlock(voutcomb, i)) return out; } else { if (!out.writeBlock(vout, i)) return out; } } out.writeStop(); readStop(); return(out); } /* SpatRaster SpatRaster::focal1(std::vector w, std::vector m, double fillvalue, bool narm, bool naonly, std::string fun, SpatOptions &opt) { SpatRaster out = geometry(1); if (nlyr() > 1) { SpatOptions ops(opt); out.addWarning("focal computations are only done for the first input layer"); std::vector lyr = {0}; *this = subset(lyr, ops); } if (!source[0].hasValues) { return(out); } bool wmat = false; if (m.size() > 1) { wmat = true; } else if (w.size() == 1) { w.push_back(w[0]); } if (w.size() != 2) { out.setError("size of w is not 1 or 2"); return out; } if ((w[0] % 2) == 0 || (w[1] % 2) == 0) { out.setError("w must be odd sized"); return out; } if (w[0] < 3 && w[1] < 3) { out.setError("w must be > 1"); return out; } unsigned ww = w[0] * w[1]; if (ww < 9) { out.setError("not a meaningful window"); return out; } if (wmat && (ww != m.size())) { out.setError("weight matrix error"); return out; } if (!readStart()) { out.setError(getError()); return(out); } opt.ncopies += 2 * ww; if (!out.writeStart(opt)) { readStop(); return out; } std::function&, bool)> fFun = getFun(fun); std::vector v; if (naonly) { int mid = ww / 2; for (size_t i = 0; i < out.bs.n; i++) { std::vector fv = focal_values(w, fillvalue, out.bs.row[i], out.bs.nrows[i]); v.resize(out.bs.nrows[i] * ncol(), NAN); if (wmat) { for (size_t j=0; j x(fv.begin()+off, fv.begin()+off+ww); double midv = x[mid]; if (std::isnan(midv)) { v[j] = fFun(x, narm); } else { v[j] = midv; } } } if (!out.writeBlock(v, i)) return out; } } else { for (size_t i = 0; i < out.bs.n; i++) { std::vector fv = focal_values(w, fillvalue, out.bs.row[i], out.bs.nrows[i]); v.resize(out.bs.nrows[i] * ncol()); if (wmat) { if (narm) { for (size_t j=0; j x(fv.begin()+off, fv.begin()+off+ww); v[j] = fFun(x, narm); } } if (!out.writeBlock(v, i)) return out; } } out.writeStop(); readStop(); return(out); } void focalrow(std::vector &x, std::vector n, const size_t &w1, const size_t &ww, const size_t &nc, const std::vector &fill) { x.erase(x.begin(), x.begin() + w1); x.resize(x.size() + w1); n.insert(n.begin(), fill.begin(), fill.end()); n.insert(n.end(), fill.begin(), fill.end()); for (size_t i=0; i w, std::vector m, double fillvalue, bool narm, bool naonly, std::string fun, SpatOptions &opt) { SpatRaster out = geometry(1); if (nlyr() > 1) { SpatOptions ops(opt); out.addWarning("focal computations are only done for the first input layer"); std::vector lyr = {0}; *this = subset(lyr, ops); } if (!source[0].hasValues) { return(out); } bool wmat = false; if (m.size() > 1) { wmat = true; } else if (w.size() == 1) { w.push_back(w[0]); } if (w.size() != 2) { out.setError("size of w is not 1 or 2"); return out; } if ((w[0] % 2) == 0 || (w[1] % 2) == 0) { out.setError("w must be odd sized"); return out; } if (w[0] < 3 && w[1] < 3) { out.setError("w must be > 1"); return out; } size_t nc = ncol(); size_t nr = nrow(); if (w[0] > (nr*2)) { out.setError("nrow(w) > 2 * nrow(x)"); return out; // w[0] = nr*2; // w[0] = std::fmod(w[0], 2) == 0 ? w[0]+1 : w[0]; } if (w[1] > (nc*2)) { out.setError("ncol(w) > 2 * ncol(x)"); return out; // w[1] = nc*2; // w[1] = std::fmod(w[1], 2) == 0 ? w[1]+1 : w[1]; } unsigned ww = w[0] * w[1]; if (ww < 9) { out.setError("not a meaningful window"); return out; } if (wmat && (ww != m.size())) { out.setError("weight matrix error"); return out; } if (!readStart()) { out.setError(getError()); return(out); } opt.ncopies += std::max(1, (int)(nc * ww / ncell())); opt.minrows = w[0] > nr ? nr : w[0]; if (!out.writeStart(opt)) { readStop(); return out; } std::function&, bool)> fFun = getFun(fun); size_t hw0 = w[0]/2; std::vector fill(hw0, fillvalue); std::vector fvals(nc * ww, fillvalue); std::vector vout; for (size_t i = 0; i < out.bs.n; i++) { if (i==0) { if (i == (out.bs.n-1)) { vout.resize(out.bs.nrows[i]* nc); } else { vout.resize((out.bs.nrows[i]-hw0) * nc); } } else if (i == (out.bs.n-1)) { vout.resize((out.bs.nrows[i] + 2 * hw0)* nc); } else if (i == 1) { vout.resize(out.bs.nrows[i]* nc); } std::vector vin = readValues(out.bs.row[i], out.bs.nrows[i]); size_t start= 0; if (i == 0) { for (size_t r=0; r row(vin.begin()+off, vin.begin()+off+nc); focalrow(fvals, row, w[1], ww, nc, fill); start++; } } for (size_t r=start; r< out.bs.nrows[i]; r++) { unsigned off1 = r*nc; std::vector row(vin.begin()+off1, vin.begin()+off1+nc); focalrow(fvals, row, w[1], ww, nc, fill); unsigned off2 = (r-start)*nc; for (size_t j=0; j x(fvals.begin()+offset, fvals.begin()+offset+ww); if (wmat) { vout[off2+j] = 0; for (size_t k=0; k row(nc, fillvalue); start = out.bs.nrows[i] - hw0; for (size_t r=0; r<(m*hw0); r++) { unsigned off = (start+r)*nc; focalrow(fvals, row, w[1], ww, nc, fill); for (size_t j=0; j x(fvals.begin()+offset, fvals.begin()+offset+ww); if (wmat) { vout[off+j] = 0; for (size_t k=0; k. #include template void recycle(std::vector &v, unsigned n) { size_t s = v.size(); v.resize(n); for (size_t i=s; i void recycle(std::vector &v, unsigned n) { size_t s = v.size(); if (s > n) { v.resize(n); } else if (s < n) { v.reserve(n); for (size_t i=s; i void recycle(std::vector &x, std::vector &y) { size_t xsize = x.size(); size_t ysize = y.size(); if (xsize != ysize) { size_t n = std::max(xsize, ysize); if (xsize > ysize) { y.resize(n); for (size_t i=ysize; i void rep(std::vector &v, unsigned n) { size_t s = v.size(); v.reserve(n * s); for (size_t i=1; i void rep_each(std::vector &v, unsigned n) { if (n == 1) return; std::vector vv = v; size_t s = v.size(); v.resize(0); v.reserve(n * s); for (size_t j=0; j void rep_each_vect(std::vector &v, std::vector n) { std::vector vv = v; v.resize(0); size_t nsum = 0; for (size_t i=0; i std::vector seq(T start, T end, T increment) { std::vector out; if (increment <= 0) return out; if (start >= end) return out; size_t s = floor((end - start) / increment); out.reserve(s); for (size_t i=0; i<=s; i++) { T val = start + i * increment; out.push_back(val); } return out; } template std::vector seq_steps(T start, T end, size_t steps) { double increment = (end - start) / (double) steps; std::vector out; out.reserve(steps); for (size_t i=0; i<=steps; i++) { T val = start + i * increment; out.push_back(val); } return out; } terra/src/raster_methods.cpp0000644000175000017500000025561114201035750016046 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . //#include #include "spatRasterMultiple.h" #include "recycle.h" #include "vecmath.h" //#include "vecmath.h" #include #include "math_utils.h" #include "file_utils.h" #include "string_utils.h" /* std::vector flat(std::vector> v) { unsigned s1 = v.size(); unsigned s2 = v[0].size(); std::size_t s = s1 * s2; std::vector result(s); for (size_t i=0; i 1) { SpatOptions ops(opt); out.addWarning("only processing the first layer"); std::vector lyr = {0}; *this = subset(lyr, ops); } if (!hasValues()) { return(out); } if (n >= ncell()) { return isnotnan(opt); } std::vector sel; if (!readStart()) { return(out); } BlockSize bs = getBlockSize(opt); for (size_t i = 0; i < bs.n; i++) { std::vector v; readBlock(v, out.bs, i); for (size_t j=0; j c2) { std::swap(c1, c2); } r1 = std::min(std::max(r1, (int_64)0), nr); r2 = std::min(std::max(r2, (int_64)0), nr); if (r1 > r2) { std::swap(r1, r2); } double xn = xFromCol(c1) - 0.5 * xrs; double xx = xFromCol(c2) + 0.5 * xrs; double yx = yFromRow(r1) + 0.5 * yrs; double yn = yFromRow(r2) - 0.5 * yrs; return SpatExtent(xn, xx, yn, yx); } SpatExtent SpatRaster::ext_from_cell(double cell) { std::vector cells = {cell}; std::vector> rc = rowColFromCell(cells); return ext_from_rc(rc[0][0], rc[0][0], rc[1][0], rc[1][0]); } std::vector SpatRaster::make_tiles(SpatRaster x, bool expand, bool narm, std::string filename, SpatOptions &opt) { std::vector ff; if (!hasValues()) { setError("input raster has no values"); return ff; } x = x.geometry(1, false, false, false); SpatExtent e = getExtent(); if (expand) { x = x.extend(e, "out", opt); } x = x.crop(e, "out", opt); std::vector d(x.ncell()); std::iota(d.begin(), d.end(), 1); std::string fext = getFileExt(filename); std::string f = noext(filename); ff.reserve(d.size()); size_t nl = nlyr(); for (size_t i=0; i rmin = out.range_min(); size_t cnt = 0; for (double &v : rmin) { if (std::isnan(v)) cnt++; } if (cnt == nl) { remove(fout.c_str()); continue; } } ff.push_back(fout); } } return ff; } bool SpatRaster::get_aggregate_dims(std::vector &fact, std::string &message ) { unsigned fs = fact.size(); if ((fs > 3) | (fs == 0)) { message = "argument 'fact' should have length 1, 2, or 3"; return false; } auto min_value = *std::min_element(fact.begin(),fact.end()); if (min_value < 1) { message = "values in argument 'fact' should be > 0"; return false; } auto max_value = *std::max_element(fact.begin(),fact.end()); if (max_value == 1) { message = "all values in argument 'fact' are 1, nothing to do"; return false; } fact.resize(6); if (fs == 1) { fact[1] = fact[0]; fact[2] = 1; } else if (fs == 2) { fact[2] = 1; } // int dy = dim[0], dx = dim[1], dz = dim[2]; fact[0] = fact[0] < 1 ? 1 : fact[0]; fact[0] = fact[0] > nrow() ? nrow() : fact[0]; fact[1] = fact[1] < 1 ? 1 : fact[1]; fact[1] = fact[1] > ncol() ? ncol() : fact[1]; fact[2] = std::max(unsigned(1), std::min(fact[2], nlyr())); // new dimensions: rows, cols, lays fact[3] = std::ceil(double(nrow()) / fact[0]); fact[4] = std::ceil(double(ncol()) / fact[1]); fact[5] = std::ceil(double(nlyr()) / fact[2]); return true; } std::vector SpatRaster::get_aggregate_dims2(std::vector fact) { // for use with R std::string message = ""; get_aggregate_dims(fact, message); return(fact); } std::vector> SpatRaster::get_aggregates(std::vector &in, size_t nr, std::vector dim) { // dim 0, 1, 2, are the aggregations factors dy, dx, dz // and 3, 4, 5 are the new nrow, ncol, nlyr // adjust for chunk //dim[3] = std::ceil(double(nr) / dim[0]); //size_t bpC = dim[3]; size_t bpC = std::ceil(double(nr) / dim[0]); size_t dy = dim[0], dx = dim[1], dz = dim[2]; size_t bpR = dim[4]; size_t bpL = bpR * bpC; // new number of layers size_t newNL = dim[5]; // new number of rows, adjusted for additional (expansion) rows size_t adjnr = bpC * dy; // number of aggregates size_t nblocks = (bpR * bpC * newNL); // cells per aggregate size_t blockcells = dx * dy * dz; // output: each row is a block std::vector< std::vector > a(nblocks, std::vector(blockcells, std::numeric_limits::quiet_NaN())); size_t nc = ncol(); // size_t ncells = ncell(); size_t ncells = nr * nc; size_t nl = nlyr(); size_t lstart, rstart, cstart, lmax, rmax, cmax, f, lj, cell; for (size_t b = 0; b < nblocks; b++) { lstart = dz * (b / bpL); rstart = (dy * (b / bpR)) % adjnr; cstart = dx * (b % bpR); lmax = std::min(nl, (lstart + dz)); rmax = std::min(nr, (rstart + dy)); // nrow -> nr cmax = std::min(nc, (cstart + dx)); f = 0; for (size_t j = lstart; j < lmax; j++) { lj = j * ncells; for (size_t r = rstart; r < rmax; r++) { cell = lj + r * nc; for (size_t c = cstart; c < cmax; c++) { a[b][f] = in[cell + c]; f++; } } } } return(a); } void compute_aggregates(const std::vector &in, std::vector &out, size_t nr, size_t nc, size_t nl, std::vector dim, std::function&, bool)> fun, bool narm) { // dim 0, 1, 2, are the aggregations factors dy, dx, dz // and 3, 4, 5 are the new nrow, ncol, nlyr size_t dy = dim[0], dx = dim[1], dz = dim[2]; // size_t bpC = dim[3]; // adjust for chunk // size_t bpC = std::ceil(double(nr) / dim[0]); size_t bpC = std::ceil((double)nr / (double)dim[0]); size_t bpR = dim[4]; size_t bpL = bpR * bpC; // new number of layers size_t newNL = dim[5]; // new number of rows, adjusted for additional (expansion) rows size_t adjnr = bpC * dy; // number of aggregates size_t nblocks = (bpR * bpC * newNL); // cells per aggregate size_t blockcells = dx * dy * dz; // output: each row is a block out = std::vector(nblocks, NAN); // size_t nl = nlyr(); // size_t nc = ncol(); size_t ncells = nr * nc; size_t lstart, rstart, cstart, lmax, rmax, cmax, f, lj, cell; for (size_t b = 0; b < nblocks; b++) { lstart = dz * (b / bpL); rstart = (dy * (b / bpR)) % adjnr; cstart = dx * (b % bpR); lmax = std::min(nl, (lstart + dz)); rmax = std::min(nr, (rstart + dy)); // nrow -> nr cmax = std::min(nc, (cstart + dx)); f = 0; std::vector a(blockcells, NAN); for (size_t j = lstart; j < lmax; j++) { lj = j * ncells; for (size_t r = rstart; r < rmax; r++) { cell = lj + r * nc; for (size_t c = cstart; c < cmax; c++) { a[f] = in[cell + c]; f++; } } } out[b] = fun(a, narm); } } SpatRaster SpatRaster::aggregate(std::vector fact, std::string fun, bool narm, SpatOptions &opt) { SpatRaster out; std::string message = ""; bool success = get_aggregate_dims(fact, message); // fact 0, 1, 2, are the aggregation factors dy, dx, dz // and 3, 4, 5 are the new nrow, ncol, nlyr if (!success) { out.setError(message); return out; } SpatExtent extent = getExtent(); double xmax = extent.xmin + fact[4] * fact[1] * xres(); double ymin = extent.ymax - fact[3] * fact[0] * yres(); SpatExtent e = SpatExtent(extent.xmin, xmax, ymin, extent.ymax); out = SpatRaster(fact[3], fact[4], fact[5], e, ""); out.source[0].srs = source[0].srs; // there is much more. categories, time. should use geometry and then // set extent and row col if (fact[5] == nlyr()) { out.setNames(getNames()); } if (!source[0].hasValues) { return out; } if (!haveFun(fun)) { out.setError("unknown function argument"); return out; } /* size_t ifun = std::distance(f.begin(), it); std::string gstring = ""; if (ifun > 0) { std::vector gf {"average", "min", "max", "med", "mode"}; gstring = gf[ifun-1]; } #ifdef useGDAL #if GDAL_VERSION_MAJOR >= 3 if (gstring != "") { out = warper(out, "", gstring, opt); return out; } #endif #endif */ std::function&, bool)> agFun = getFun(fun); //BlockSize bs = getBlockSize(4, opt.get_memfrac()); opt.progress *= 300; BlockSize bs = getBlockSize(opt); //bs.n = floor(nrow() / fact[0]); # ambiguous on solaris bs.n = std::floor(static_cast (nrow() / fact[0])); bs.nrows = std::vector(bs.n, fact[0]); bs.row.resize(bs.n); for (size_t i =0; i vin, v; readValues(vin, bs.row[i], bs.nrows[i], 0, nc); compute_aggregates(vin, v, bs.nrows[i], nc, nlyr(), fact, agFun, narm); if (!out.writeValues(v, i, 1)) return out; //if (!out.writeValuesRect(v, i, 1, 0, outnc)) return out; } out.writeStop(); readStop(); return(out); } SpatRaster SpatRaster::weighted_mean(SpatRaster w, bool narm, SpatOptions &opt) { SpatRaster out; if (nlyr() != w.nlyr()) { out.setError("nlyr of data and weights are different"); return out; } SpatOptions topt(opt); out = arith(w, "*", topt); out = out.summary("sum", narm, topt); SpatRaster wsum = w.summary("sum", narm, topt); return out.arith(wsum, "/", opt); } SpatRaster SpatRaster::weighted_mean(std::vector w, bool narm, SpatOptions &opt) { SpatOptions topt(opt); recycle(w, nlyr()); SpatRaster out = arith(w, "*", false, topt); out = out.summary("sum", narm, topt); double wsum = vsum(w, narm); return out.arith(wsum, "/", false, opt); } SpatRaster SpatRaster::separate(std::vector classes, double keepvalue, double othervalue, SpatOptions &opt) { SpatRaster out; if (nlyr() > 1) { out.setError("input may only have one layer"); return out; } if (classes.size() == 0) { SpatOptions topt(opt); std::vector> rc = unique(false, topt); classes = rc[0]; } std::vector uc(classes.size()); for (size_t i=0; i snms(n); for (size_t i=0; i v; readBlock(v, out.bs, i); size_t nn = v.size(); std::vector vv(nn * n, NAN); for (size_t j=0; j m, SpatOptions &opt) { SpatRaster out = geometry(); if (m.size() == 0) { out.setError("no matches supplied"); return(out); } if (!hasValues()) { out.setError("input has no values"); return(out); } int hasNAN = 0; for (size_t i=0; i v; readBlock(v, out.bs, i); std::vector vv(v.size(), 0); for (size_t j=0; j> SpatRaster::is_in_cells(std::vector m, SpatOptions &opt) { std::vector> out(nlyr()); if (m.size() == 0) { return(out); } if (!hasValues()) { return(out); } bool hasNAN = false; for (size_t i=0; i v; readBlock(v, bs, i); size_t cellperlayer = bs.nrows[i] * nc; for (size_t j=0; j minv, std::vector maxv, std::vector minq, std::vector maxq, std::vector smin, std::vector smax, SpatOptions &opt) { SpatRaster out = geometry(); if (!hasValues()) return(out); size_t nl = nlyr(); recycle(minv, nl); recycle(maxv, nl); recycle(minq, nl); recycle(maxq, nl); recycle(smin, nl); recycle(smax, nl); std::vector> q(nl); std::vector useS(nl, false); std::vector mult(nl); for (size_t i=0; i= maxv[i]) { out.setError("maxv must be larger than minv"); return out; } if ((!std::isnan(smin[i])) && (!std::isnan(smax[i]))) { if (smin[i] >= smax[i]) { out.setError("smax must be larger than smin"); return out; } useS[i] = true; q[i] = {smin[i], smax[i]}; } else { if (minq[i] >= maxq[i]) { out.setError("maxq must be larger than minq"); return out; } if ((minq[i] < 0) || (maxq[i] > 1)) { out.setError("minq and maxq must be between 0 and 1"); return out; } } } std::vector hR = hasRange(); for (size_t i=0; i rmn = range_min(); std::vector rmx = range_max(); q[i] = {rmn[i], rmx[i]}; } else { std::vector probs = {minq[i], maxq[i]}; SpatOptions xopt(opt); std::vector v = getValues(i, xopt); q[i] = vquantile(v, probs, true); } } mult[i] = maxv[i] / (q[i][1]-q[i][0]); } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i = 0; i < out.bs.n; i++) { std::vector v; readBlock(v, out.bs, i); size_t nc = out.bs.nrows[i] * ncol(); for (size_t j=0; j maxv[lyr]) v[j] = maxv[lyr]; } if (!out.writeBlock(v, i)) return out; } readStop(); out.writeStop(); return(out); } SpatRaster SpatRaster::apply(std::vector ind, std::string fun, bool narm, std::vector nms, SpatOptions &opt) { recycle(ind, nlyr()); std::vector ui = vunique(ind); unsigned nl = ui.size(); SpatRaster out = geometry(nl); recycle(nms, nl); out.setNames(nms); if (!haveFun(fun)) { out.setError("unknown function argument"); return out; } if (!hasValues()) return(out); if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } out.bs = getBlockSize(opt); // #ifdef useRcpp // out.pbar = new Progress(out.bs.n+2, opt.show_progress(bs.n)); // out.pbar->increment(); // #endif std::vector> v(nl); std::vector ird(ind.size()); std::vector jrd(ind.size()); for (size_t i=0; i&, bool)> theFun = getFun(fun); for (size_t i=0; i a; readBlock(a, out.bs, i); unsigned nc = out.bs.nrows[i] * ncol(); std::vector b(nc * nl); for (size_t j=0; j v, m; for (size_t i = 0; i < out.bs.n; i++) { readValues(v, out.bs.row[i], out.bs.nrows[i], 0, ncol()); x.readValues(m, out.bs.row[i], out.bs.nrows[i], 0, ncol()); recycle(v, m); if (inverse) { if (std::isnan(maskvalue)) { for (size_t i=0; i < v.size(); i++) { if (!std::isnan(m[i])) { v[i] = updatevalue; } } } else { for (size_t i=0; i < v.size(); i++) { if (m[i] != maskvalue) { v[i] = updatevalue; } } } } else { if (std::isnan(maskvalue)) { for (size_t i=0; i < v.size(); i++) { if (std::isnan(m[i])) { v[i] = updatevalue; } } } else { for (size_t i=0; i < v.size(); i++) { if (m[i] == maskvalue) { v[i] = updatevalue; } } } } if (!out.writeBlock(v, i)) return out; } out.writeStop(); readStop(); x.readStop(); return(out); } SpatRaster SpatRaster::mask(SpatRaster x, bool inverse, std::vector maskvalues, double updatevalue, SpatOptions &opt) { maskvalues = vunique(maskvalues); if (maskvalues.size() == 1) { return mask(x, inverse, maskvalues[0], updatevalue, opt); } unsigned nl = std::max(nlyr(), x.nlyr()); SpatRaster out = geometry(nl, true); if (!out.compare_geom(x, false, true, opt.get_tolerance(), true, true, true, false)) { return(out); } if (!readStart()) { out.setError(getError()); return(out); } if (!x.readStart()) { out.setError(x.getError()); return(out); } bool maskNA = false; for (int i = maskvalues.size()-1; i>=0; i--) { if (std::isnan(maskvalues[i])) { maskNA = true; maskvalues.erase(maskvalues.begin()+i); } } if (!out.writeStart(opt)) { readStop(); return out; } std::vector v, m; for (size_t i = 0; i < out.bs.n; i++) { readValues(v, out.bs.row[i], out.bs.nrows[i], 0, ncol()); x.readValues(m, out.bs.row[i], out.bs.nrows[i], 0, ncol()); recycle(v, m); if (inverse) { for (size_t i=0; i < v.size(); i++) { if (maskNA && std::isnan(m[i])) { v[i] = updatevalue; } else { for (size_t j=0; j < maskvalues.size(); j++) { if (m[i] != maskvalues[j]) { v[i] = updatevalue; break; } } } } } else { for (size_t i=0; i < v.size(); i++) { if (maskNA && std::isnan(m[i])) { v[i] = updatevalue; } else { for (size_t j=0; j < maskvalues.size(); j++) { if (m[i] == maskvalues[j]) { v[i] = updatevalue; break; } } } } } if (!out.writeBlock(v, i)) return out; } out.writeStop(); readStop(); x.readStop(); return(out); } SpatRaster SpatRaster::mask(SpatVector x, bool inverse, double updatevalue, bool touches, SpatOptions &opt) { SpatRaster out; if (!hasValues()) { out.setError("SpatRaster has no values"); return out; } if (inverse) { out = rasterizeLyr(x, updatevalue, NAN, touches, true, opt); } else { SpatOptions topt(opt); out = rasterizeLyr(x, 1, 0, touches, false, topt); if (out.hasError()) { return out; } if (std::isnan(updatevalue)) { out = mask(out, false, 0, updatevalue, opt); } else { out = mask(out, false, 0, updatevalue, topt); out = out.mask(*this, false, NAN, NAN, opt); } } return(out); } SpatRaster SpatRaster::transpose(SpatOptions &opt) { SpatRaster out = geometry(nlyr(), true); SpatExtent eold = getExtent(); SpatExtent enew = getExtent(); enew.xmin = eold.ymin; enew.xmax = eold.ymax; enew.ymin = eold.xmin; enew.ymax = eold.xmax; out.setExtent(enew, false, ""); out.source[0].ncol = nrow(); out.source[0].nrow = ncol(); if (!hasValues()) return out; if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i=0; i < out.bs.n; i++) { unsigned nr = nrow(); unsigned nc = out.bs.nrows[i]; std::vector v; readValues(v, 0, nr, out.bs.row[i], nc); std::vector vv(v.size()); for (size_t lyr=0; lyr v; size_t firstrow, lastrow, firstcol, lastcol; if (std::isnan(value)) { for (r=0; rfirstrow; r--) { readValues(v, r, 1, 0, ncol()); if (std::count_if(v.begin(), v.end(), [](double d) { return std::isnan(d); } ) < ncl) { break; } } lastrow = std::max(std::min(r+padding, nrow()), size_t(0)); if (lastrow < firstrow) { std::swap(firstrow, lastrow); } size_t c; for (c=0; cfirstcol; c--) { readValues(v, 0, nrow(), c, 1); if (std::count_if( v.begin(), v.end(), [](double d) { return std::isnan(d); } ) < nrl) { break; } } lastcol = std::max(std::min(c+padding, ncol()), size_t(0)); } else { for (r=0; rfirstrow; r--) { readValues(v, r, 1, 0, ncol()); if (std::count( v.begin(), v.end(), value) < ncl) { break; } } lastrow = std::max(std::min(r+padding, nrow()), size_t(0)); if (lastrow < firstrow) { std::swap(firstrow, lastrow); } size_t c; for (c=0; cfirstcol; c--) { readValues(v, 0, nrow(), c, 1); if (std::count( v.begin(), v.end(), value) < nrl) { break; } } lastcol = std::max(std::min(c+padding, ncol()), size_t(0)); } readStop(); if (lastcol < firstcol) { std::swap(firstcol, lastcol); } std::vector res = resolution(); double xr = res[0]; double yr = res[1]; SpatExtent e = SpatExtent(xFromCol(firstcol)-0.5*xr, xFromCol(lastcol)+0.5*xr, yFromRow(lastrow)-0.5*yr, yFromRow(firstrow)+0.5*yr); return( crop(e, "near", opt) ) ; } void clamp_vector(std::vector &v, double low, double high, bool usevalue) { size_t n = v.size(); if (usevalue) { for (size_t i=0; i high ) { v[i] = high; } } } else { for (size_t i=0; i high)) { v[i] = NAN; } } } } SpatRaster SpatRaster::clamp(double low, double high, bool usevalue, SpatOptions &opt) { SpatRaster out = geometry(nlyr(), true); if (low > high) { out.setError("lower clamp value cannot be larger than the higher clamp value"); return out; } if (!hasValues()) { out.setError("cannot clamp a raster with no values"); return out; } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i = 0; i < out.bs.n; i++) { std::vector v; readBlock(v, out.bs, i); clamp_vector(v, low, high, usevalue); if (!out.writeBlock(v, i)) return out; } readStop(); out.writeStop(); return(out); } SpatRaster SpatRaster::selRange(SpatRaster x, int z, int recycleby, SpatOptions &opt) { int nl = nlyr(); z = std::max(1, std::min(z, nl)); size_t nrecs = 1; if (recycleby > 1 && recycleby < nl) { nrecs = nl / recycleby; } else { recycleby = 0; } SpatRaster out = geometry( z * nrecs ); if (!out.compare_geom(x, false, false, opt.get_tolerance())) { return(out); } if (!hasValues()) return(out); if (x.nlyr() > 1) { out.setError("index raster must have only one layer"); return out; } if (!x.hasValues()) { out.setError("index raster has no values"); return out; } if (!readStart()) { out.setError(getError()); return(out); } if (!x.readStart()) { out.setError(x.getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i=0; i v, idx; readBlock(v, out.bs, i); x.readBlock(idx, out.bs, i); size_t is = idx.size(); std::vector vv(is*z*nrecs, NAN); size_t ncell = out.bs.nrows[i] * ncol(); // same as is? for (size_t j=0; j= 0) && (start < nl)) { int zz = std::min(nl-start, z); // do not surpass the last layer for (int i=0; i= 0) && (index < nl)) { // vv[j] = v[j + index * ncell]; // } //} if (!out.writeBlock(vv, i)) return out; } readStop(); x.readStop(); out.writeStop(); return(out); } SpatRaster SpatRaster::rapply(SpatRaster x, double first, double last, std::string fun, bool clamp, bool narm, SpatOptions &opt) { SpatRaster out = geometry(1); if (!haveFun(fun)) { out.setError("unknown function argument"); return out; } bool sval = !std::isnan(first); bool eval = !std::isnan(last); if (sval && eval) { out.setError("arguments `first` or `last` must be NA. See `app` for other cases"); return out; } int start = sval ? first-1 : -99; int end = eval ? last-1 : -999; if (!out.compare_geom(x, false, false, opt.get_tolerance())) { return(out); } if (!x.hasValues()) { out.setError("index raster has no values"); return out; } unsigned expnl = 2 - (sval + eval); if (x.nlyr() != expnl) { out.setError("index raster must have " + std::to_string(expnl) + "layer(s)"); return out; } if (!hasValues()) { out.setError("no values in input"); return(out); } std::function&, bool)> theFun = getFun(fun); int nl = nlyr(); if (!out.writeStart(opt)) { readStop(); return out; } if (!readStart()) { out.setError(getError()); return(out); } if (!x.readStart()) { out.setError(x.getError()); return(out); } for (size_t i=0; i v, idx; readBlock(v, out.bs, i); x.readBlock(idx, out.bs, i); size_t ncell = out.bs.nrows[i] * ncol(); std::vector vv(ncell, NAN); for (size_t j=0; j= nl ? (nl-1) : end; } if ((start <= end) && (end < nl) && (start >= 0)) { std::vector se; se.reserve(end-start+1); for (int k = start; k<=end; k++){ size_t off = k * ncell + j; se.push_back(v[off]); } vv[j] = theFun(se, narm); } } if (!out.writeBlock(vv, i)) return out; } readStop(); x.readStop(); out.writeStop(); return(out); } std::vector> SpatRaster::rappvals(SpatRaster x, double first, double last, bool clamp, bool all, double fill, size_t startrow, size_t nrows) { std::vector> r; bool sval = !std::isnan(first); bool eval = !std::isnan(last); if (sval && eval) { setError("first or last must be NA. See `app` for other cases"); return r; } int start = sval ? first-1 : 0; int end = eval ? last-1 : 0; if (!compare_geom(x, false, false, 0.1)) { return(r); } if (!hasValues()) { return r; } if (!x.hasValues()) { setError("index raster has no values"); return r; } unsigned expnl = 2 - (sval + eval); if (x.nlyr() != expnl) { setError("index raster must have " + std::to_string(expnl) + "layer(s)"); return r; } int nl = nlyr(); if (!readStart()) { return(r); } if (!x.readStart()) { setError(x.getError()); return(r); } std::vector v, idx; readValues(v, startrow, nrows, 0, ncol()); x.readValues(idx, startrow, nrows, 0, ncol()); size_t ncell = nrows * ncol(); r.resize(ncell); for (size_t j=0; j= nl ? (nl-1) : end; } bool inrange = (start <= end) && (end < nl) && (start >= 0); if (all) { if (inrange) { r[j].resize(nl, fill); for (int k = start; k<=end; k++){ size_t off = k * ncell + j; r[j][k] = v[off]; } } else { r[j].resize(nl, NAN); } } else if (inrange) { r[j].reserve(end-start+1); for (int k=start; k<=end; k++){ size_t off = k * ncell + j; r[j].push_back(v[off]); } } else { r[j].push_back(NAN); } } readStop(); x.readStop(); return(r); } bool disaggregate_dims(std::vector &fact, std::string &message ) { unsigned fs = fact.size(); if ((fs > 3) | (fs == 0)) { message = "argument 'fact' should have length 1, 2, or 3"; return false; } auto min_value = *std::min_element(fact.begin(),fact.end()); if (min_value < 1) { message = "values in argument 'fact' should be > 0"; return false; } auto max_value = *std::max_element(fact.begin(),fact.end()); if (max_value == 1) { message = "all values in argument 'fact' are 1, nothing to do"; return false; } fact.resize(3); if (fs == 1) { fact[1] = fact[0]; } fact[2] = 1; return true; } SpatRaster SpatRaster::disaggregate(std::vector fact, SpatOptions &opt) { SpatRaster out = geometry(nlyr(), true); std::string message = ""; bool success = disaggregate_dims(fact, message); if (!success) { out.setError(message); return out; } out.source[0].nrow = out.source[0].nrow * fact[0]; out.source[0].ncol = out.source[0].ncol * fact[1]; out.source[0].nlyr = out.source[0].nlyr * fact[2]; if (!hasValues()) { return out; } opt.ncopies = 2*fact[0]*fact[1]*fact[2]; BlockSize bs = getBlockSize(opt); //opt.set_blocksizemp(); unsigned nc = ncol(); unsigned nl = nlyr(); std::vector newrow(nc*fact[1]); if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i = 0; i < bs.n; i++) { std::vector v, vout; readValues(v, bs.row[i], bs.nrows[i], 0, nc); vout.reserve(v.size() * fact[0] * fact[1] * fact[2]); for (size_t lyr=0; lyr f {"row", "col", "cell", "x", "y", "chess"}; bool test = std::find(f.begin(), f.end(), value) == f.end(); if (test) { out.setError("not a valid init option"); return out; } if (!out.writeStart(opt)) { readStop(); return out; } size_t nc = ncol(); std::vector v; if (value == "row") { for (size_t i = 0; i < out.bs.n; i++) { v.resize(nc * out.bs.nrows[i]); for (size_t j = 0; j < out.bs.nrows[i]; j++) { size_t r = out.bs.row[i] + j + plusone; for (size_t k = 0; k < nc; k++) { v[j*nc+k] = r; } } if (!out.writeBlock(v, i)) return out; } source[0].range_min.resize(1, 0 + plusone); source[0].range_max.resize(1, nrow() - 1 + plusone); source[0].hasRange.resize(1, true); } else if (value == "col") { std::vector cnn(nc); double start = plusone ? 1 : 0; std::iota(cnn.begin(), cnn.end(), start); size_t oldnr = 0; for (size_t i = 0; i < out.bs.n; i++) { if (oldnr != out.bs.nrows[i]) { v = cnn; recycle(v, out.bs.nrows[i] * nc); } if (!out.writeBlock(v, i)) return out; } source[0].range_min.resize(1, 0 + plusone); source[0].range_max.resize(1, nc - 1 + plusone); source[0].hasRange.resize(1, true); } else if (value == "cell") { for (size_t i = 0; i < out.bs.n; i++) { v.resize(nc * out.bs.nrows[i]); size_t firstcell = cellFromRowCol(out.bs.row[i], 0); firstcell = plusone ? firstcell + 1 : firstcell; std::iota(v.begin(), v.end(), firstcell); if (!out.writeBlock(v, i)) return out; } source[0].range_min.resize(1, 0 + plusone); source[0].range_max.resize(1, ncell() - 1 + plusone); source[0].hasRange.resize(1, true); } else if (value == "x") { std::vector col(nc); std::iota(col.begin(), col.end(), 0); std::vector xcoords = xFromCol(col); size_t oldnr = 0; for (size_t i = 0; i < out.bs.n; i++) { if (oldnr != out.bs.nrows[i]) { v = xcoords; recycle(v, out.bs.nrows[i] * nc); } if (!out.writeBlock(v, i)) return out; } source[0].range_min.resize(1, xcoords[0]); source[0].range_max.resize(1, xcoords[nc-1]); source[0].hasRange.resize(1, true); } else if (value == "y") { for (size_t i = 0; i < out.bs.n; i++) { v.resize(out.bs.nrows[i] * nc ); for (size_t j = 0; j < out.bs.nrows[i]; j++) { double y = yFromRow(out.bs.row[i] + j); for (size_t k = 0; k < nc; k++) { v[j*nc+k] = y; } } if (!out.writeBlock(v, i)) return out; } source[0].range_min.resize(1, yFromRow(0)); source[0].range_max.resize(1, yFromRow(nrow()-1)); source[0].hasRange.resize(1, true); } else if (value == "chess") { std::vector a(nc); std::vector b(nc); for (size_t i=0; i v; for (size_t i = 0; i < out.bs.n; i++) { if ((out.bs.row[i]%2) == 0) { v = a; v.insert(v.end(), b.begin(), b.end()); } else { v = b; v.insert(v.end(), b.begin(), b.end()); } recycle(v, out.bs.nrows[i] * nc); if (!out.writeBlock(v, i)) return out; } source[0].range_min.resize(1, 0); source[0].range_max.resize(1, 1); source[0].hasRange.resize(1, true); } out.writeStop(); return(out); } SpatRaster SpatRaster::init(std::vector values, SpatOptions &opt) { SpatRaster out = geometry(); if (!out.writeStart(opt)) { return out; } unsigned nc = ncol(); unsigned nl = nlyr(); if (values.size() == 1) { double val = values[0]; std::vector v; for (size_t i = 0; i < out.bs.n; i++) { v.resize(out.bs.nrows[i]*nc*nl, val); if (!out.writeBlock(v, i)) return out; } source[0].range_min.resize(1, val); source[0].range_max.resize(1, val); source[0].hasRange.resize(1, true); } else { int over = 0; for (size_t i = 0; i < out.bs.n; i++) { if (over > 0) { std::vector newv(values.begin()+over, values.end()); newv.insert(newv.end(), values.begin(), values.begin()+over); values = newv; } std::vector v = values; recycle(v, out.bs.nrows[i]*nc); recycle(v, out.bs.nrows[i]*nc*nl); over = v.size() % values.size(); if (!out.writeBlock(v, i)) return out; } } out.writeStop(); return(out); } SpatRaster SpatRaster::rotate(bool left, SpatOptions &opt) { unsigned nc = ncol(); unsigned nl = nlyr(); unsigned hnc = (nc / 2); double addx = hnc * xres(); if (left) { addx = -addx; } SpatRaster out = geometry(nlyr(), true, true, true); SpatExtent outext = out.getExtent(); outext.xmin = outext.xmin + addx; outext.xmax = outext.xmax + addx; out.setExtent(outext, true); if (!hasValues()) return out; if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i=0; i < out.bs.n; i++) { std::vector a; readBlock(a, out.bs, i); std::vector b; b.reserve(a.size()); for (size_t j=0; j < nl; j++) { for (size_t r=0; r < out.bs.nrows[i]; r++) { unsigned s1 = j * out.bs.nrows[i] * nc + r * nc; unsigned e1 = s1 + hnc; b.insert(b.end(), a.begin()+e1, a.begin()+s1+nc); b.insert(b.end(), a.begin()+s1, a.begin()+e1); } } if (!out.writeBlock(b, i)) return out; } out.writeStop(); readStop(); return(out); } bool SpatRaster::shared_basegeom(SpatRaster &x, double tol, bool test_overlap) { if (!compare_origin(x.origin(), tol)) return false; if (!about_equal(xres(), x.xres(), xres() * tol)) return false; if (!about_equal(yres(), x.yres(), yres() * tol)) return false; if (test_overlap) { SpatExtent e = x.getExtent(); e = e.intersect(getExtent()); if (!e.valid()) return false; } return true; } SpatRaster SpatRaster::cover(SpatRaster x, std::vector values, SpatOptions &opt) { unsigned nl = std::max(nlyr(), x.nlyr()); SpatRaster out = geometry(nl, true); bool rmatch = false; if (out.compare_geom(x, false, false, opt.get_tolerance(), true)) { rmatch = true; } else { // if (!shared_basegeom(x, 0.1, true)) { out.setError("raster dimensions do not match"); return(out); // } else { // out.msg.has_error = false; // out.msg.error = ""; // SpatExtent e = getExtent(); // SpatExtent xe = x.getExtent(); // double prec = std::min(xres(), yres())/1000; // if (!xe.compare(e, "<=", prec)) { // SpatOptions xopt(opt); // x = x.crop(e, "near", xopt); // } // } } if (!x.hasValues()) { return *this; } if (!hasValues()) { if (rmatch) { return x.deepCopy(); } else { SpatExtent e = getExtent(); return x.extend(e, "near", opt); } } if (!readStart()) { out.setError(getError()); return(out); } if (!x.readStart()) { out.setError(x.getError()); return(out); } if (!out.writeStart(opt)) { readStop(); x.readStop(); return out; } if (values.size() == 1) { double value=values[0]; for (size_t i = 0; i < out.bs.n; i++) { std::vector v, m; readValues(v, out.bs.row[i], out.bs.nrows[i], 0, ncol()); x.readValues(m, out.bs.row[i], out.bs.nrows[i], 0, ncol()); recycle(v, m); if (std::isnan(value)) { for (size_t i=0; i < v.size(); i++) { if (std::isnan(v[i])) { v[i] = m[i]; } } } else { for (size_t i=0; i < v.size(); i++) { if (v[i] == value) { v[i] = m[i]; } } } if (!out.writeBlock(v, i)) return out; } } else { values = vunique(values); bool hasNA = false; for (int i = values.size()-1; i>=0; i--) { if (std::isnan(values[i])) { hasNA = true; values.erase(values.begin()+i); } } for (size_t i = 0; i < out.bs.n; i++) { std::vector v, m; readValues(v, out.bs.row[i], out.bs.nrows[i], 0, ncol()); x.readValues(m, out.bs.row[i], out.bs.nrows[i], 0, ncol()); recycle(v, m); for (size_t i=0; i < v.size(); i++) { if (hasNA) { if (std::isnan(v[i])) { v[i] = m[i]; continue; } } for (size_t i=0; i v; readValues(v, bs.row[i], bs.nrows[i], 0, ncol()); unsigned row1 = out.rowFromY(yFromRow(bs.row[i])); unsigned row2 = out.rowFromY(yFromRow(bs.row[i]+bs.nrows[i]-1)); unsigned col1 = out.colFromX(xFromCol(0)); unsigned col2 = out.colFromX(xFromCol(ncol()-1)); if (!out.writeValuesRect(v, row1, row2-row1+1, col1, col2-col1+1)) return out; } readStop(); out.writeStop(); return(out); } SpatRaster SpatRaster::crop(SpatExtent e, std::string snap, SpatOptions &opt) { SpatRaster out = geometry(nlyr(), true, true, true); if ( !e.valid() ) { out.setError("invalid extent"); return out; } e = e.intersect(out.getExtent()); if ( !e.valid() ) { out.setError("extents do not overlap"); return out; } out.setExtent(e, true, snap); if (!hasValues() ) { if (opt.get_filename() != "") { out.addWarning("ignoring filename argument because there are no cell values"); } return(out); } double xr = xres(); double yr = yres(); SpatExtent outext = out.getExtent(); unsigned col1 = colFromX(outext.xmin + 0.5 * xr); unsigned col2 = colFromX(outext.xmax - 0.5 * xr); unsigned row1 = rowFromY(outext.ymax - 0.5 * yr); unsigned row2 = rowFromY(outext.ymin + 0.5 * yr); std::vector hw = hasWindow(); bool haswin = hw[0]; for (size_t i=1; i v; for (size_t i = 0; i < out.bs.n; i++) { readValues(v, row1+out.bs.row[i], out.bs.nrows[i], col1, ncols); if (!out.writeBlock(v, i)) return out; } out.writeStop(); readStop(); return(out); } SpatRaster SpatRaster::cropmask(SpatVector v, std::string snap, SpatOptions &opt) { SpatOptions copt(opt); SpatRaster out = crop(v.extent, snap, copt); return out.mask(v, false, NAN, false, opt); } SpatRaster SpatRaster::flip(bool vertical, SpatOptions &opt) { SpatRaster out = geometry(nlyr(), true, true, true); if (!hasValues()) return out; if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } unsigned nc = ncol(); unsigned nl = nlyr(); if (vertical) { for (size_t i=0; i < out.bs.n; i++) { std::vector a, b; size_t ii = out.bs.n - 1 - i; readBlock(a, out.bs, ii); b.reserve(a.size()); for (size_t j=0; j < out.nlyr(); j++) { size_t offset = j * out.bs.nrows[ii] * nc; for (size_t k=0; k < out.bs.nrows[ii]; k++) { unsigned start = offset + (out.bs.nrows[ii] - 1 - k) * nc; b.insert(b.end(), a.begin()+start, a.begin()+start+nc); } } if (!out.writeBlock(b, i)) return out; } } else { for (size_t i=0; i < out.bs.n; i++) { std::vector a, b; readBlock(a, out.bs, i); b.reserve(a.size()); unsigned lyrrows = nl * out.bs.nrows[i]; for (size_t j=0; j < lyrrows; j++) { unsigned start = j * nc; unsigned end = start + nc; std::vector v(a.begin()+start, a.begin()+end); std::reverse(v.begin(), v.end()); b.insert(b.end(), v.begin(), v.end()); } if (!out.writeBlock(b, i)) return out; } } out.writeStop(); readStop(); return(out); } SpatRaster SpatRaster::reverse(SpatOptions &opt) { SpatRaster out = geometry(nlyr(), true, true, true); if (!hasValues()) return out; if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } unsigned nc = ncol(); unsigned nl = nlyr(); for (size_t i=0; i < out.bs.n; i++) { size_t ii = out.bs.n - 1 - i; std::vector a, b; readBlock(a, out.bs, ii); b.reserve(a.size()); unsigned lyrrows = nl * out.bs.nrows[ii]; for (size_t j=0; j < lyrrows; j++) { unsigned start = (lyrrows - 1 - j) * nc; unsigned end = start + nc; std::vector v(a.begin()+start, a.begin()+end); std::reverse(v.begin(), v.end()); b.insert(b.end(), v.begin(), v.end()); } if (!out.writeBlock(b, i)) return out; } out.writeStop(); readStop(); return(out); } SpatRaster SpatRaster::shift(double x, double y, SpatOptions &opt) { SpatRaster out = deepCopy(); SpatExtent outext = out.getExtent(); outext.xmin = outext.xmin + x; outext.xmax = outext.xmax + x; outext.ymin = outext.ymin + y; outext.ymax = outext.ymax + y; out.setExtent(outext, true); return out; } bool SpatRaster::compare_origin(std::vector x, double tol) { std::vector y = origin(); if (!about_equal(x[0], y[0], xres() * tol)) return false; if (!about_equal(x[1], y[1], yres() * tol)) return false; return true; } /* SpatRaster SpatRasterCollection::merge(SpatOptions &opt) { SpatRaster out; unsigned n = size(); if (n == 0) { out.setError("empty collection"); return(out); } if (n == 1) { out = ds[0].deepCopy(); return(out); } bool any_hasvals = false; if (ds[0].hasValues()) any_hasvals = true; out = ds[0].geometry(ds[0].nlyr(), true); std::vector orig = ds[0].origin(); SpatExtent e = ds[0].getExtent(); unsigned nl = ds[0].nlyr(); for (size_t i=1; i v = r.readValues(bs.row[j], bs.nrows[j], 0, r.ncol()); unsigned row1 = out.rowFromY(r.yFromRow(bs.row[j])); unsigned row2 = out.rowFromY(r.yFromRow(bs.row[j]+bs.nrows[j]-1)); unsigned col1 = out.colFromX(r.xFromCol(0)); unsigned col2 = out.colFromX(r.xFromCol(r.ncol()-1)); unsigned ncols = col2-col1+1; unsigned nrows = row2-row1+1; recycle(v, ncols * nrows * nl); if (!out.writeValues(v, row1, nrows, col1, ncols)) return out; } r.readStop(); } out.writeStop(); return(out); } */ SpatRaster SpatRasterCollection::merge(SpatOptions &opt) { return mosaic("first", opt); } SpatRaster SpatRasterCollection::mosaic(std::string fun, SpatOptions &opt) { SpatRaster out; std::vector f {"first", "sum", "mean", "median", "min", "max"}; if (std::find(f.begin(), f.end(), fun) == f.end()) { out.setError("not a valid function"); return out; } unsigned n = size(); if (n == 0) { out.setError("empty collection"); return(out); } if (n == 1) { out = ds[0].deepCopy(); return(out); } std::vector hvals(n); hvals[0] = ds[0].hasValues(); SpatExtent e = ds[0].getExtent(); unsigned nl = ds[0].nlyr(); std::vector resample(n, false); for (size_t i=1; i=0; i--) { if (!hvals[i]) { erase(i); } } n = size(); if (size() == 0) { return out; } SpatExtent eout = out.getExtent(); double hyr = out.yres()/2; std::string warn = ""; for (size_t i=0; i hascats = ds[i].hasCategories(); std::string method = hascats[0] ? "near" : "bilinear"; ds[i] = ds[i].warper(temp, "", method, false, false, topt); if (ds[i].hasError()) { out.setError(ds[i].getError()); return out; } warn = "rasters did not align and were resampled"; } } if (warn != "") out.addWarning(warn); if (!out.writeStart(opt)) { return out; } SpatOptions sopt(opt); sopt.progressbar = false; std::vector v; for (size_t i=0; i < out.bs.n; i++) { eout.ymax = out.yFromRow(out.bs.row[i]) + hyr; eout.ymin = out.yFromRow(out.bs.row[i] + out.bs.nrows[i] - 1) - hyr; SpatRasterStack s; for (size_t j=0; j 0) { SpatRaster r = s.summary(fun, true, sopt); if (r.hasError()) { out.setError("internal error: " + r.getError()); out.writeStop(); return out; } if (!r.getValuesSource(0, v)) { out.setError("internal error: " + r.getError()); out.writeStop(); return out; } recycle(v, ncls); } else { v = std::vector(ncls, NAN); } if (!out.writeBlock(v, i)) return out; } out.writeStop(); return(out); } SpatRaster SpatRasterCollection::morph(SpatRaster &x, SpatOptions &opt) { SpatRaster out; unsigned n = size(); if (n == 0) { out.setError("empty collection"); return(out); } std::string filename = opt.get_filename(); opt.set_filenames({""}); SpatExtent e = x.getExtent(); out.source.resize(0); SpatRaster g = x.geometry(); SpatOptions topt(opt); for (size_t i=0; i hasCats = ds[i].hasCategories(); // this should be done by layer bool call = true; for (size_t j=0; j &x, double &n) { for (size_t i=0; i &v, std::string fun, bool narm, double &stat, double &stat2,double &n, size_t step) { if (v.size() == 0) return; if (fun == "sum") { double s = vsum(v, narm); if (step > 0) { std::vector ss = {stat, s}; stat = vsum(ss, narm); } else { stat = s; } } else if (fun == "mean") { double s = vsum(v, narm); if (step > 0) { std::vector ss = {stat, s}; stat = vsum(ss, narm); } else { stat = s; } if (narm) { notisnan(v, n); } else { n += v.size(); } } else if (fun == "rms") { if (narm) { notisnan(v, n); } else { n += v.size(); } double s = vsum2(v, narm); if (step > 0) { std::vector ss = {stat, s}; stat = vsum(ss, narm); } else { stat = s; } } else if (fun == "min") { double s = vmin(v, narm); if (step > 0) { std::vector ss = {stat, s}; stat = vmin(ss, narm); } else { stat = s; } } else if (fun == "max") { double s = vmax(v, narm); if (step > 0) { std::vector ss = {stat, s}; stat = vmax(ss, narm); } else { stat = s; } } else if (fun == "range") { double sn = vmin(v, narm); double sx = vmax(v, narm); if (step > 0) { std::vector ss1 = {stat, sn}; stat = vmin(ss1, narm); std::vector ss2 = {stat2, sx}; stat2 = vmax(ss2, narm); } else { stat = sn; stat2 = sx; } } else if (fun == "sd") { if (narm) { notisnan(v, n); } else { n += v.size(); } double s1 = vsum(v, narm); double s2 = vsum2(v, narm); if (step > 0) { std::vector ss1 = {stat, s1}; stat = vsum(ss1, narm); std::vector ss2 = {stat2, s2}; stat2 = vsum(ss2, narm); } else { stat = s1; stat2 = s2; } } else if (fun == "notNA" || fun == "isNA") { notisnan(v, n); } } SpatDataFrame SpatRaster::global(std::string fun, bool narm, SpatOptions &opt) { SpatDataFrame out; std::vector f {"sum", "mean", "min", "max", "range", "rms", "sd", "std", "stdpop", "isNA", "notNA"}; if (std::find(f.begin(), f.end(), fun) == f.end()) { out.setError("not a valid function"); return(out); } if (!hasValues()) { out.setError("SpatRaster has no values"); return(out); } std::string sdfun = fun; if ((fun == "std") || (fun == "sdpop")) { sdfun = "std"; fun = "sd"; } std::vector stats(nlyr()); std::vector stats2(nlyr()); std::vector n(nlyr()); if (!readStart()) { out.setError(getError()); return(out); } BlockSize bs = getBlockSize(opt); for (size_t i=0; i v; readBlock(v, bs, i); unsigned off = bs.nrows[i] * ncol() ; for (size_t lyr=0; lyr vv = { v.begin()+offset, v.begin()+offset+off }; do_stats(vv, fun, narm, stats[lyr], stats2[lyr], n[lyr], i); } } readStop(); if (fun=="mean") { for (size_t lyr=0; lyr 0) { stats[lyr] = stats[lyr] / n[lyr]; } else { stats[lyr] = NAN; } } } else if (fun=="rms") { // rms = sqrt(sum(x^2)/(n-1)) for (size_t lyr=0; lyr 0) { stats[lyr] = sqrt(stats[lyr] / (n[lyr]-1)); } else { stats[lyr] = NAN; } } } else if (fun == "sd") { for (size_t lyr=0; lyr 0) { double mn = stats[lyr] / n[lyr]; double mnsq = mn * mn; double mnsumsq = stats2[lyr] / n[lyr]; if (sdfun == "std") { stats[lyr] = sqrt(mnsumsq - mnsq); } else { stats[lyr] = sqrt((mnsumsq - mnsq) * n[lyr]/(n[lyr]-1)); } } else { stats[lyr] = NAN; } } } else if (fun == "notNA") { for (size_t lyr=0; lyr f {"sum", "mean"}; if (std::find(f.begin(), f.end(), fun) == f.end()) { out.setError("not a valid function"); return(out); } if (!hasValues()) { out.setError("SpatRaster has no values"); return(out); } if (weights.nlyr() != 1) { out.setError("The weights raster must have 1 layer"); return(out); } if (!compare_geom(weights, false, false, opt.get_tolerance(), true)) { out.setError( msg.getError() ); return(out); } std::vector stats(nlyr()); double stats2 = 0; std::vector n(nlyr()); std::vector w(nlyr()); if (!readStart()) { out.setError(getError()); return(out); } if (!weights.readStart()) { out.setError(weights.getError()); return(out); } BlockSize bs = getBlockSize(opt); for (size_t i=0; i v, wv; readValues(v, bs.row[i], bs.nrows[i], 0, ncol()); weights.readValues(wv, bs.row[i], bs.nrows[i], 0, ncol()); unsigned off = bs.nrows[i] * ncol() ; for (size_t lyr=0; lyr vv(v.begin()+offset, v.begin()+offset+off); for (size_t j=0; j 0 && w[lyr] != 0) { stats[lyr] /= w[lyr]; } else { stats[lyr] = NAN; } } out.add_column(stats, "weighted_mean"); } else { out.add_column(stats, "weighted_sum"); } return(out); } SpatRaster SpatRaster::scale(std::vector center, bool docenter, std::vector scale, bool doscale, SpatOptions &opt) { SpatRaster out; SpatOptions opts(opt); SpatDataFrame df; if (docenter) { if (center.size() == 0) { df = global("mean", true, opts); center = df.getD(0); } if (doscale) { out = arith(center, "-", false, opts); } else { out = arith(center, "-", false, opt); } } if (doscale) { if (scale.size() == 0) { // divide by sd if centered, and the root mean square otherwise. // rms = sqrt(sum(x^2)/(n-1)); if centered rms == sd if (docenter) { df = out.global("rms", true, opts); } else { df = global("rms", true, opts); } scale = df.getD(0); } if (docenter) { out = out.arith(scale, "/", false, opt); } else { out = arith(scale, "/", false, opt); } } return out; } void reclass_vector(std::vector &v, std::vector> rcl, bool right_closed, bool left_right_closed, bool lowest, bool othNA) { size_t nc = rcl.size(); // should be 2 or 3 double NAval = NAN; size_t n = v.size(); unsigned nr = rcl[0].size(); if (nc == 1) { std::vector rc = rcl[0]; std::sort(rc.begin(), rc.end()); if (right_closed) { if (lowest) { for (size_t i=0; i rc[nr-1])) { v[i] = NAval; } else { for (size_t j=1; j rc[nr-1])) { v[i] = NAval; } else { for (size_t j=1; j rc[nr-1])) { v[i] = NAval; } else if (v[i] == rc[nr-1]) { v[i] = nr-2; // safe because there must be at least 2 classes } else { for (size_t j=1; j= rc[nr-1])) { v[i] = NAval; } else { for (size_t j=1; j= rcl[0][j]) & (v[i] <= rcl[1][j])) { v[i] = rcl[2][j]; found = true; break; } } if ((othNA) & (!found)) { v[i] = NAval; } } } } else if (right_closed) { if (lowest) { // include lowest value (left) of interval double lowval = rcl[0][0]; double lowres = rcl[2][0]; for (size_t i=1; i rcl[0][j]) & (v[i] <= rcl[1][j])) { v[i] = rcl[2][j]; found = true; break; } } if ((othNA) & (!found)) { v[i] = NAval; } } } } else { // !lowest for (size_t i=0; i rcl[0][j]) & (v[i] <= rcl[1][j])) { v[i] = rcl[2][j]; found = true; break; } } if ((othNA) & (!found)) { v[i] = NAval; } } } } } else { // left closed if (lowest) { // which here means highest because right=FALSE double lowval = rcl[1][0]; double lowres = rcl[2][0]; for (size_t i=0; i lowval) { lowval = rcl[1][i]; lowres = rcl[2][i]; } } for (size_t i=0; i= rcl[0][j]) & (v[i] < rcl[1][j])) { v[i] = rcl[2][j]; found = true; break; } } if ((othNA) & (!found)) { v[i] = NAval; } } } } else { //!dolowest for (size_t i=0; i= rcl[0][j]) & (v[i] < rcl[1][j])) { v[i] = rcl[2][j]; found = true; break; } } if ((othNA) & (!found)) { v[i] = NAval; } } } } } } } SpatRaster SpatRaster::replaceValues(std::vector from, std::vector to, long nl, SpatOptions &opt) { SpatRaster out = geometry(nl); bool multi = false; if (nl > 1) { if (nlyr() > 1) { out.setError("cannot create layer-varying replacement with multi-layer input"); return out; } multi = true; } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } if (multi) { size_t tosz = to.size() / nl; size_t nlyr = out.nlyr(); for (size_t i = 0; i < out.bs.n; i++) { std::vector v; readBlock(v, out.bs, i); size_t vs = v.size(); v.reserve(vs * nlyr); for (size_t lyr = 1; lyr < nlyr; lyr++) { v.insert(v.end(), v.begin(), v.begin()+vs); } for (size_t lyr = 0; lyr < nlyr; lyr++) { std::vector tolyr(to.begin()+lyr*tosz, to.begin()+(lyr+1)*tosz); recycle(tolyr, from); size_t offset = lyr*vs; for (size_t j=0; j< from.size(); j++) { if (std::isnan(from[j])) { for (size_t k=offset; k<(offset+vs); k++) { v[k] = std::isnan(v[k]) ? tolyr[j] : v[k]; } } else { std::replace(v.begin()+offset, v.begin()+(offset+vs), from[j], tolyr[j]); } } } if (!out.writeBlock(v, i)) return out; } } else { recycle(to, from); for (size_t i = 0; i < out.bs.n; i++) { std::vector v; readBlock(v, out.bs, i); for (size_t j=0; j< from.size(); j++) { if (std::isnan(from[j])) { for (double &d : v) d = std::isnan(d) ? to[j] : d; } else { std::replace(v.begin(), v.end(), from[j], to[j]); } } if (!out.writeBlock(v, i)) return out; } } readStop(); out.writeStop(); return(out); } SpatRaster SpatRaster::reclassify(std::vector> rcl, unsigned openclosed, bool lowest, bool othersNA, bool bylayer, bool brackets, SpatOptions &opt) { SpatRaster out = geometry(); size_t nc = rcl.size(); size_t nr = rcl[0].size(); size_t nl = nlyr(); if (nl == 1) bylayer = false; size_t maxnc = 3 + nl * bylayer; size_t rcldim = nc; if (bylayer) { if (((nc != maxnc) && (nc != (maxnc-1))) || nr < 1) { out.setError("reclass matrix is not correct. Should be nlyr(x) plus 1 or 2"); return out; } rcldim = nc - (nl-1); } else { if (nc < 1 || nc > 3 || nr < 1) { out.setError("matrix must have 1, 2 or 3 columns, and at least one row"); return out; } } //bool left = openclosed == 0; bool right = openclosed != 0 ; bool leftright = openclosed == 2; if (nc == 1) { if (nr == 1) { int breaks = rcl[0][0]; if (breaks < 2) { out.setError("cannot classify with a single number that is smaller than 2"); return out; } std::vector hr = hasRange(); bool hasR = true; for (size_t i=0; i mn = range_min(); std::vector mx = range_max(); double mnv = vmin(mn, true); double mxv = vmax(mx, true); rcl[0] = seq_steps(mnv, mxv, breaks); } size_t rn = rcl[0].size(); if ((rn > 1) && (rn < 256)) { std::vector s; if (brackets) { std::string bleft = ((!right) || lowest) ? "[" : "("; std::string bright = right ? "]" : ")"; s.push_back(bleft+ double_to_string(rcl[0][0]) + "–" + double_to_string(rcl[0][1]) + bright); bleft = right ? "(" : "["; for (size_t i=2; i<(rn-1); i++) { s.push_back(bleft + double_to_string(rcl[0][i-1]) + "–" + double_to_string(rcl[0][i]) + bright); } bright = (right || lowest) ? "]" : ")"; s.push_back(bleft + double_to_string(rcl[0][rn-2]) + "–" + double_to_string(rcl[0][rn-1]) + bright); } else { for (size_t i=1; i u(s.size()); std::iota(u.begin(), u.end(), 0); std::vector nms = getNames(); for (size_t i=0; i rcl[1][i]) { out.setError("'from' larger than 'to': (" + std::to_string(rcl[0][i]) + " - " + std::to_string(rcl[1][i]) +")"); return out; } } } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } if (bylayer) { std::vector> lyrrcl(rcldim+1); for (size_t i=0; i v; readBlock(v, out.bs, i); for (size_t lyr = 0; lyr < nl; lyr++) { unsigned offset = lyr * off; lyrrcl[rcldim] = rcl[rcldim+lyr]; std::vector vx(v.begin()+offset, v.begin()+offset+off); reclass_vector(vx, lyrrcl, right, leftright, lowest, othersNA); std::copy(vx.begin(), vx.end(), v.begin()+offset); } if (!out.writeBlock(v, i)) return out; } } else { for (size_t i = 0; i < out.bs.n; i++) { std::vector v; readBlock(v, out.bs, i); reclass_vector(v, rcl, right, leftright, lowest, othersNA); if (!out.writeBlock(v, i)) return out; } } readStop(); out.writeStop(); return(out); } SpatRaster SpatRaster::reclassify(std::vector rcl, unsigned nc, unsigned openclosed, bool lowest, bool othersNA, bool bylayer, bool brackets, SpatOptions &opt) { SpatRaster out; if ((rcl.size() % nc) != 0) { out.setError("incorrect length of reclassify matrix"); return(out); } size_t maxnc = 3 + bylayer * (nlyr() - 1); unsigned nr = rcl.size() / nc; if (nc > maxnc) { out.setError("incorrect number of columns in reclassify matrix"); return(out); } std::vector< std::vector> rc(nc); for (size_t i=0; i(rcl.begin()+(i*nr), rcl.begin()+(i+1)*nr); } out = reclassify(rc, openclosed, lowest, othersNA, bylayer, brackets, opt); return out; } std::vector> clump_getRCL(std::vector> rcl, size_t n) { std::vector> rcl2(rcl[0].size()); for (size_t i=0; i> out(2); for (size_t i=0; i lost = out[0]; lost.push_back(n); size_t sub = 0; for (size_t i=0; i &v, size_t n, std::vector& d, size_t cstart, std::vector>& rcl, size_t &ncps) { d.erase(std::remove_if(d.begin(), d.end(), [](const double& v) { return std::isnan(v); }), d.end()); std::sort(d.begin(), d.end()); d.erase(std::unique(d.begin(), d.end()), d.end()); size_t nd = d.size(); if (nd == 0) { v[n] = ncps; ncps++; return; } else if (nd == 1) { v[n] = d[0]; return; } v[n] = d[0]; for (size_t i=0; i &v, std::vector& above, const size_t &dirs, size_t &ncps, const size_t &nr, const size_t &nc, std::vector> &rcl, bool is_global) { size_t nstart = ncps; bool d4 = dirs == 4; size_t stopnc = nc-1; std::vector d; //first row, no row above it, use "above" //first cell //Rcpp::Rcout << "r x i v[i] nc v[i] nc" << std::endl; if ( !std::isnan(v[0]) ) { //Rcpp::Rcout << 0 << " ff " << 0 << " " << v[0] << " " << ncps << " " ; if (d4) { if (std::isnan(above[0])) { v[0] = ncps; // new patch ncps++; } else { v[0] = above[0]; // same as above } } else if (is_global) { //d8 global d = {above[0], above[1], above[stopnc]} ; clump_replace(v, 0, d, nstart, rcl, ncps); } else { //d8 d = {above[0], above[1]} ; clump_replace(v, 0, d, nstart, rcl, ncps); } //Rcpp::Rcout << v[0] << " " << ncps << std::endl; } // other cells for (size_t i=1; i(v.begin()+off, v.end()); } SpatRaster SpatRaster::clumps(int directions, bool zeroAsNA, SpatOptions &opt) { SpatRaster out = geometry(1); if (nlyr() > 1) { SpatOptions ops(opt); std::vector nms = getNames(); if (ops.names.size() == nms.size()) { nms = opt.names; } for (size_t i=0; i lyr = {(unsigned)i}; ops.names = {nms[i]}; SpatRaster x = subset(lyr, ops); x = x.clumps(directions, zeroAsNA, ops); out.addSource(x, false, ops); } if (opt.get_filename() != "") { out = out.writeRaster(opt); } return out; } if (!(directions == 4 || directions == 8)) { out.setError("directions must be 4 or 8"); return out; } if (!hasValues()) { out.setError("cannot compute clumps for a raster with no values"); return out; } std::vector dim = {nrow(), ncol()}; std::string tempfile = ""; std::vector d, v, vv; if (!readStart()) { out.setError(getError()); return(out); } std::string filename = opt.get_filename(); if (filename != "") { bool overwrite = opt.get_overwrite(); std::string errmsg; if (!can_write(filename, overwrite, errmsg)) { out.setError(errmsg + " (" + filename +")"); return(out); } } if (opt.names.size() == 0) { opt.names = {"patches"}; } opt.set_filenames({""}); if (!out.writeStart(opt)) { return out; } size_t nc = ncol(); size_t ncps = 1; std::vector above(nc, NAN); std::vector> rcl(2); bool is_global = is_global_lonlat(); for (size_t i = 0; i < out.bs.n; i++) { readBlock(v, out.bs, i); if (zeroAsNA) { std::replace(v.begin(), v.end(), 0.0, (double)NAN); } broom_clumps(v, above, directions, ncps, out.bs.nrows[i], nc, rcl, is_global); if (!out.writeBlock(v, i)) return out; // perhaps here keep track of unique values, so that gaps can be removed } out.writeStop(); readStop(); opt.set_filenames({filename}); if (rcl[0].size() > 0) { std::vector> rc = clump_getRCL(rcl, ncps); out = out.reclassify(rc, 3, true, false, false, false, opt); } else if (filename != "") { out = out.writeRaster(opt); } return out; } bool SpatRaster::replaceCellValues(std::vector &cells, std::vector &v, bool bylyr, SpatOptions &opt) { size_t cs = cells.size(); size_t vs = v.size(); if (vs == 1) { bylyr = false; recycle(v, cs); } else if (bylyr && (vs != (cs*nlyr()))) { setError("lengths of of cells and values do not match"); return false; } else if (cs != vs) { setError("lengths of of cells and values do not match"); return false; } size_t nc = ncell(); size_t ns = nsrc(); if (!hasValues()) { *this = init({NAN}, opt); } for (size_t i=0; i nms; if (type == "hsv") { nms = {"hue", "saturation", "value"}; hsv = true; } else if (type == "hsi") { nms = {"hue", "saturation", "intensity"}; hsi = true; } else if (type == "hsl") { nms = {"hue", "saturation", "lightness"}; //hsl = true; } else { out.setError("unknown type. Should be one of 'hsv', 'hsi' or 'hsl'"); return out; } out.setNames(nms); out.rgbtype = type; if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { return out; } size_t nc=ncol(); for (size_t i = 0; i < out.bs.n; i++) { std::vector v; readBlock(v, out.bs, i); size_t n = out.bs.nrows[i] * nc; size_t n2 = n * 2; size_t iR = rgblyrs[0] * n; size_t iG = rgblyrs[1] * n; size_t iB = rgblyrs[2] * n; for (size_t j = 0; j < n; j++) { double R = v[j + iR] / 255.; double G = v[j + iG] / 255.; double B = v[j + iB] / 255.; double m = std::min(std::min(R, G), B); double M = std::max(std::max(R, G), B); double C = (M - m); if ((M == 0) || (C == 0)) { v[j] = 0; // H (hue) v[j+n] = 0; // S (saturation) if (hsv) { v[j+n2] = M; // V } else if (hsi) { v[j+n2] = (R + G + B) / 3; // I } else { v[j+n2] = (M + m) / 2; // L } } else { // S if (hsv) { v[j+n] = C / M; v[j+n2] = M; // value } else if (hsi) { v[j+n2] = (R + G + B) / 3; // I v[j+n] = 1 - m / v[j+n2]; } else { double L = (M + m) / 2; v[j+n] = C / (1 - std::fabs(2 * L - 1)); v[j+n2] = L; } // H if (hsi) { double H = ((R-G)+(R-B))/2.0; H = H/sqrt((R-G)*(R-G) + (R-B)*(G-B)); H = acos(H); if (B > G) { H = 2 * M_PI - H; } v[j] = H/(2 * M_PI); //v[j] = acos( sqrt((((R-G) + (R-B)) / 2) / pow((R - G),2) + (R-B)*(G-B)) ); } else { if (M == R) { v[j] = 60 * (G - B) / C; } else if (M == G) { v[j] = 60 * ((B - R) / C) + 120; } else { v[j] = 60 * ((R - G) / C) + 240; } v[j] = v[j] < 0 ? (v[j] + 360) / 360 : v[j] / 360; } } } if (!out.writeBlock(v, i)) return out; } out.writeStop(); readStop(); return out; } SpatRaster SpatRaster::hsx2rgb(SpatOptions &opt) { SpatRaster out = geometry(); if (nlyr() != 3) { out.setError("x must have three layers"); return out; } if (!hasValues()) { out.setError("no cell values"); return out; } bool hsv=false; bool hsl=false; if (rgbtype == "hsv") { hsv = true; } else if (rgbtype == "hsl") { hsl = true; } else if (rgbtype != "hsi") { out.setError("input color scheme should be one of 'hsv', 'hsi' or 'hsl'"); return out; } std::vector nms={"red", "green", "blue"}; out.setNames(nms); out.rgb = true; out.rgblyrs = {0,1,2}; if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { return out; } size_t nc=ncol(); for (size_t i = 0; i < out.bs.n; i++) { std::vector v; readBlock(v, out.bs, i); size_t n = out.bs.nrows[i] * nc; size_t n2 = n * 2; for (size_t j = 0; j < n; j++) { if (std::isnan(v[j])) continue; double H = v[j] * 360; double S = v[j+n]; double X, C, m; if (hsv) { double V = v[j + n2]; C = V * S; m = V - C; X = C * (1 - std::fabs(std::fmod((H / 60.), 2) - 1)); } else if (hsl) { double L = v[j + n2]; C = (1 - std::fabs(2*L-1)) * S; m = L - C/2; X = C * (1 - std::fabs(std::fmod((H / 60.), 2) - 1)); } else { // hsi double I = v[j + n2]; double Z = 1 - std::fabs((std::fmod(H/60., 2.)) -1); C = (3 * I * S) / (1 + Z); X = C * Z; m = I * (1-S); } if (H < 60) { v[j]=C; v[j+n]=X; v[j+n2]=0; } else if (H < 120) { v[j]=X; v[j+n]=C; v[j+n2]=0; } else if (H < 180) { v[j]=0; v[j+n]=C; v[j+n2]=X; } else if (H < 240) { v[j]=0; v[j+n]=X; v[j+n2]=C; } else if (H < 300) { v[j]=X; v[j+n]=0; v[j+n2]=C; } else { v[j]=C; v[j+n]=0; v[j+n2]=X; } v[j] = (v[j] + m) * 255; v[j+n] = (v[j+n] + m) * 255; v[j+n2] = (v[j+n2] + m) * 255; } if (!out.writeBlock(v, i)) return out; } out.writeStop(); readStop(); return out; } terra/src/rasterize.cpp0000644000175000017500000003473314201626441015036 0ustar nileshnilesh #include "ogr_spatialref.h" #include "spatRaster.h" #include "file_utils.h" #include "gdal_alg.h" #include "ogrsf_frmts.h" #include "spatFactor.h" #include "recycle.h" #include "gdalio.h" SpatRaster rasterizePoints(SpatVector p, SpatRaster r, std::vector values, double background, SpatOptions &opt) { r.setError("not implemented in C++ yet"); return(r); } SpatRaster SpatRaster::hardCopy(SpatOptions &opt) { SpatRaster out = geometry(-1, true, true); if (!hasValues()) { out.addWarning("raster has no values"); return out; } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i = 0; i < out.bs.n; i++) { std::vector v; readBlock(v, out.bs, i); if (!out.writeBlock(v, i)) return out; } out.writeStop(); readStop(); return(out); } /* gdalcopy GDALDatasetH hSrcDS = GDALOpenEx(out.source[0].filename.c_str(), GDAL_OF_RASTER | GDAL_OF_UPDATE, NULL, NULL, NULL); if(hSrcDS == NULL) { out.setError("cannot open dataset";) return false; } GDALDriverH hDriver = GDALGetDatasetDriver(hSrcDS); GDALDatasetH hDstDS = GDALCreateCopy( hDriver, filename.c_str(), hSrcDS, FALSE, NULL, NULL, NULL ); GDALClose(hSrcDS); if(hDstDS == NULL) { out.setError("cannot create dataset"; return false; } GDALClose(hDstDS); */ bool SpatRaster::getDSh(GDALDatasetH &rstDS, SpatRaster &out, std::string &filename, std::string &driver, double &naval, bool update, double background, SpatOptions &opt) { filename = opt.get_filename(); if (filename == "") { if (canProcessInMemory(opt)) { driver = "MEM"; } else { filename = tempFile(opt.get_tempdir(), opt.pid, ".tif"); opt.set_filenames({filename}); driver = "GTiff"; } } else { driver = opt.get_filetype(); getGDALdriver(filename, driver); if (driver == "") { out.setError("cannot guess file type from filename"); return false; } std::string msg; if (!can_write(filename, opt.get_overwrite(), msg)) { out.setError(msg); return false; } } if (opt.names.size() == nlyr()) { out.setNames(opt.names); } if (update) { out = hardCopy(opt); //size_t ns = source.size(); if (!out.open_gdal(rstDS, 0, true, opt)) { return false; } } else if (!out.create_gdalDS(rstDS, filename, driver, true, background, source[0].has_scale_offset, source[0].scale, source[0].offset, opt)) { out.setError("cannot create dataset"); return false; } GDALRasterBandH hBand = GDALGetRasterBand(rstDS, 1); GDALDataType gdt = GDALGetRasterDataType(hBand); getNAvalue(gdt, naval); int hasNA; double naflag = GDALGetRasterNoDataValue(hBand, &hasNA); naval = hasNA ? naflag : naval; return true; } SpatRaster SpatRaster::rasterizeLyr(SpatVector x, double value, double background, bool touches, bool update, SpatOptions &opt) { std::string gtype = x.type(); SpatRaster out; out.setNames({"ID"}); if ( !hasValues() ) update = false; if (update) { // all lyrs out = geometry(); } else { out = geometry(1); } GDALDataset *vecDS = x.write_ogr("", "lyr", "Memory", false, true, std::vector()); if (x.hasError()) { out.setError(x.getError()); return out; } OGRLayer *poLayer = vecDS->GetLayer(0); #if GDAL_VERSION_MAJOR <= 2 && GDAL_VERSION_MINOR <= 2 OGRLayerH hLyr = poLayer; #else OGRLayerH hLyr = poLayer->ToHandle(poLayer); #endif std::vector ahLayers; ahLayers.push_back( hLyr ); std::string driver, filename; GDALDatasetH rstDS; double naval; if (!getDSh(rstDS, out, filename, driver, naval, update, background, opt)) { return out; } if (std::isnan(value)) { // passing NULL instead may also work. value = naval; } std::vector bands(out.nlyr()); std::iota(bands.begin(), bands.end(), 1); std::vector values(out.nlyr(), value); char** papszOptions = NULL; CPLErr err; if (touches) { papszOptions = CSLSetNameValue(papszOptions, "ALL_TOUCHED", "TRUE"); } err = GDALRasterizeLayers(rstDS, static_cast(bands.size()), &(bands[0]), 1, &(ahLayers[0]), NULL, NULL, &(values[0]), papszOptions, NULL, NULL); CSLDestroy(papszOptions); // for (size_t i=0; i values, double background, bool touches, bool add, bool weights, bool update, bool minmax, SpatOptions &opt) { std::string gtype = x.type(); bool ispol = gtype == "polygons"; if (weights) update = false; if (weights && ispol) { SpatOptions sopts(opt); SpatRaster wout = geometry(1); unsigned agx = 1000 / ncol(); agx = std::max((unsigned)10, agx); unsigned agy = 1000 / nrow(); agy = std::max((unsigned)10, agy); wout = wout.disaggregate({agx, agy}, sopts); field = ""; double f = agx * agy; wout = wout.rasterize(x, field, {1/f}, background, touches, add, false, false, false, sopts); wout = wout.aggregate({agx, agy}, "sum", true, opt); return wout; } SpatRaster out; if ( !hasValues() ) update = false; if (update) { out = hardCopy(opt); } else { out = geometry(1); if (field == "") { out.setNames({"layer"}); } else { out.setNames({field}); } } if (ispol && touches && add) { add = false; out.addWarning("you cannot use add and touches at the same time"); } if (field != "") { int i = x.df.get_fieldindex(field); if (i < 0) { out.setError("field " + field + " not found"); return out; } std::string dt = x.df.get_datatype(field); if (dt == "string") { //std::vector ss = ; SpatFactor f; f.set_values(x.df.getS(i)); values.resize(f.v.size()); for (size_t i=0; i u(f.labels.size()); std::iota(u.begin(), u.end(), 0); std::vector nms = getNames(); out.setLabels(0, u, f.labels, field); } if (add) { add = false; addWarning("cannot add factors"); } } else if (dt == "double") { values = x.df.getD(i); } else { std::vector v = x.df.getI(i); values.resize(v.size()); for (size_t i=0; i()); if (x.hasError()) { out.setError(x.getError()); return out; } std::vector ogrGeoms; ogrGeoms.reserve(nGeoms); OGRLayer *poLayer = vecDS->GetLayer(0); poLayer->ResetReading(); OGRFeature *poFeature; while( (poFeature = poLayer->GetNextFeature()) != NULL ) { OGRGeometry *poGeometry = poFeature->GetGeometryRef(); if (poGeometry != NULL) { OGRGeometry *copyGeom = poGeometry->clone(); ogrGeoms.push_back( copyGeom ); } OGRFeature::DestroyFeature( poFeature ); } GDALClose(vecDS); std::string errmsg, driver, filename; GDALDatasetH rstDS; double naval; if (add) { background = 0; } if (!out.getDSh(rstDS, out, filename, driver, naval, update, background, opt)) { return out; } for (double &d : values) d = std::isnan(d) ? naval : d; // passing NULL instead may also work. std::vector bands(out.nlyr()); std::iota(bands.begin(), bands.end(), 1); rep_each(values, out.nlyr()); char** papszOptions = NULL; CPLErr err; if (ispol && touches && (nGeoms > 1)) { // first to get the touches papszOptions = CSLSetNameValue(papszOptions, "ALL_TOUCHED", "TRUE"); err = GDALRasterizeGeometries(rstDS, static_cast(bands.size()), &(bands[0]), static_cast(ogrGeoms.size()), (OGRGeometryH *) &(ogrGeoms[0]), NULL, NULL, &(values[0]), papszOptions, NULL, NULL); CSLDestroy(papszOptions); if ( err != CE_None ) { out.setError("rasterization failed"); GDALClose(rstDS); for (size_t i=0; i(bands.size()), &(bands[0]), static_cast(ogrGeoms.size()), (OGRGeometryH *) &(ogrGeoms[0]), NULL, NULL, &(values[0]), NULL, NULL, NULL); } else { if (touches) { papszOptions = CSLSetNameValue(papszOptions, "ALL_TOUCHED", "TRUE"); } else if (add) { papszOptions = CSLSetNameValue(papszOptions, "MERGE_ALG", "ADD"); } err = GDALRasterizeGeometries(rstDS, static_cast(bands.size()), &(bands[0]), static_cast(ogrGeoms.size()), (OGRGeometryH *) &(ogrGeoms[0]), NULL, NULL, &(values[0]), papszOptions, NULL, NULL); CSLDestroy(papszOptions); } for (size_t i=0; i SpatRaster::rasterizeCells(SpatVector &v, bool touches, SpatOptions &opt) { // note that this is only for lines and polygons SpatOptions ropt(opt); SpatRaster r = geometry(1); SpatExtent e = getExtent(); e = e.intersect(v.getExtent()); if ( !e.valid() ) { std::vector out(1, NAN); return out; } SpatRaster rc = r.crop(e, "out", ropt); std::vector feats(1, 1) ; SpatRaster rcr = rc.rasterize(v, "", feats, NAN, touches, false, false, false, false, ropt); SpatVector pts = rcr.as_points(false, true, ropt); std::vector cells; if (pts.size() == 0) { pts = v.as_points(false, true); SpatDataFrame vd = pts.getGeometryDF(); std::vector x = vd.getD(0); std::vector y = vd.getD(1); cells = r.cellFromXY(x, y); cells.erase(std::unique(cells.begin(), cells.end()), cells.end()); if (cells.size() == 0) { cells.resize(1, NAN); } } else { SpatDataFrame vd = pts.getGeometryDF(); std::vector x = vd.getD(0); std::vector y = vd.getD(1); cells = r.cellFromXY(x, y); } return cells; } void SpatRaster::rasterizeCellsWeights(std::vector &cells, std::vector &weights, SpatVector &v, SpatOptions &opt) { // note that this is only for polygons SpatOptions ropt(opt); opt.progress = nrow()+1; SpatRaster rr = geometry(1); std::vector fact = {10, 10}; SpatExtent e = getExtent(); SpatExtent ve = v.getExtent(); e = e.intersect(ve); if ( !e.valid() ) { return; } SpatRaster r = rr.crop(v.extent, "out", ropt); r = r.disaggregate(fact, ropt); std::vector feats(1, 1) ; r = r.rasterize(v, "", feats, NAN, true, false, false, false, false, ropt); r = r.arith(100.0, "/", false, ropt); r = r.aggregate(fact, "sum", true, ropt); SpatVector pts = r.as_points(true, true, ropt); if (pts.size() == 0) { weights.resize(1); weights[0] = NAN; cells.resize(1); cells[0] = NAN; } else { SpatDataFrame vd = pts.getGeometryDF(); std::vector x = vd.getD(0); std::vector y = vd.getD(1); cells = rr.cellFromXY(x, y); weights = pts.df.dv[0]; } return; } void SpatRaster::rasterizeCellsExact(std::vector &cells, std::vector &weights, SpatVector &v, SpatOptions &opt) { SpatOptions ropt(opt); opt.progress = nrow()+1; SpatRaster r = geometry(1); r = r.crop(v.extent, "out", ropt); // if (r.ncell() < 1000) { std::vector feats(1, 1) ; r = r.rasterize(v, "", feats, NAN, true, false, false, false, false, ropt); SpatVector pts = r.as_points(true, true, ropt); if (pts.size() == 0) { weights.resize(1); weights[0] = NAN; cells.resize(1); cells[0] = NAN; } else { SpatDataFrame vd = pts.getGeometryDF(); std::vector x = vd.getD(0); std::vector y = vd.getD(1); cells = cellFromXY(x, y); SpatVector rv = r.as_polygons(false, false, false, true, ropt); std::vector csize = rv.area("m", true, {}); rv.df.add_column(csize, "area"); rv.df.add_column(cells, "cells"); rv = rv.crop(v); weights = rv.area("m", true, {}); for (size_t i=0; i feats(1, 1) ; SpatVector vv = v.as_lines(); SpatRaster b = r.rasterize(vv, "", feats, NAN, true, false, false, false, false, opt); SpatVector pts = b.as_points(true, true, opt); if (pts.nrow() > 0) { SpatDataFrame vd = pts.getGeometryDF(); std::vector x = vd.getD(0); std::vector y = vd.getD(1); cells = cellFromXY(x, y); SpatVector bv = b.as_polygons(false, false, false, true, opt); std::vector csize = bv.area("m", true, {}); bv.df.add_column(csize, "cellsize"); bv.df.add_column(cells, "cellnr"); bv = bv.crop(v); weights = bv.area("m", true, {}); for (size_t i=0; i 0) { SpatDataFrame vd = pts.getGeometryDF(); std::vector x = vd.getD(0); std::vector y = vd.getD(1); std::vector cells2 = cellFromXY(x, y); cells.insert(cells.end(), cells2.begin(), cells2.end()); weights.resize(weights.size() + cells2.size(), 1); } if (cells.size() == 0) { weights.resize(1); weights[0] = NAN; cells.resize(1); cells[0] = NAN; } } */ } terra/src/memory.cpp0000644000175000017500000000567114201035750014332 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include "spatRaster.h" #include "ram.h" bool SpatRaster::canProcessInMemory(SpatOptions &opt) { if (opt.get_todisk()) return false; double demand = size() * opt.ncopies; double supply; if (opt.get_memmax() > 0) { supply = opt.get_memmax() * opt.get_memfrac(); supply = std::min(supply, availableRAM()); } else { supply = availableRAM() * opt.get_memfrac(); } std::vector v; double maxsup = v.max_size(); //for 32 bit systems supply = std::min(supply, maxsup); return (demand < supply); } size_t SpatRaster::chunkSize(SpatOptions &opt) { double n = opt.ncopies; double frac = opt.get_memfrac(); double cells_in_row = ncol() * nlyr() * n; double supply; if (opt.get_memmax() > 0) { supply = opt.get_memmax() * opt.get_memfrac(); supply = std::min(supply, availableRAM()); } else { supply = availableRAM() * opt.get_memfrac(); } double rows = supply * frac / cells_in_row; //double maxrows = 10000; //rows = std::min(rows, maxrows); size_t urows = floor(rows); urows = std::max(urows, (size_t)opt.minrows); if (urows < 1) return (1); if (urows < nrow()){ return(urows); } else { return (nrow()); } } std::vector SpatRaster::mem_needs(SpatOptions &opt) { //returning bytes unsigned n = opt.ncopies; double memneed = ncell() * (nlyr() * n); double memavail; if (opt.get_memmax() > 0) { memavail = opt.get_memmax(); memavail = std::min(memavail, availableRAM()); } else { memavail = availableRAM(); } double frac = opt.get_memfrac(); double csize = chunkSize(opt); double inmem = canProcessInMemory(opt); std::vector out = {memneed, memavail, frac, csize, inmem} ; return out; } //BlockSize SpatRaster::getBlockSize(unsigned n, double frac, unsigned steps) { BlockSize SpatRaster::getBlockSize( SpatOptions &opt) { unsigned steps = opt.get_steps(); BlockSize bs; size_t cs; if (steps > 0) { if (steps > nrow()) { steps = nrow(); } bs.n = steps; cs = nrow() / steps; } else { cs = chunkSize(opt); bs.n = std::ceil(nrow() / double(cs)); } bs.row = std::vector(bs.n); bs.nrows = std::vector(bs.n, cs); size_t r = 0; for (size_t i =0; i= m, ,drop=FALSE] out[[i+j]] <- rgb[rgb[,p] < m, ,drop=FALSE] } i <- sapply(out, is.null) out <- out[!i] i <- sapply(out, nrow) > 0 out[i] } median_cut <- function(v) { v <- list(v) n <- 0 while ((length(v) < 129) & (length(v) > n)) { n <- length(v) v <- make_cut(v) } s <- sapply(v, function(i) max(apply(i[,-1,drop=FALSE], 2, function(j) diff(range(j))))) n <- 256 - length(v) ss <- rev(sort(s)) ss <- max(2, min(ss[1:n])) i <- which(s > ss) if (length(i) > 0) { vv <- make_cut(v[i]) v <- c(v[-i], vv) } v <- lapply(1:length(v), function(i) cbind(group=i, v[[i]])) do.call(rbind, v) } SpatRatser SpatRaster::RGB2col(std::string stretch, SpatOptions &opt) { std::vector idx = x.RGB(); SpatRaster out = geometry(1); if (idx.size() != 3) { out.setError("x does not have a valid RGB attribute"); return out; } if (vmax(idx) >= x.nlyr()) { out.setError("invalid RGB indices") } *this = subset(idx); if (stretch != "") { if (stretch == "lin") { } else if (stretch == "hist") { } else { out.addWarning("invalid stretch option"); } } v <- cbind(id=1:ncell(x), values(x)) v <- median_cut(stats::na.omit(v)) a <- aggregate(v[,3:5], list(v[,1]), median) a$cols <- grDevices::rgb(a[,2], a[,3], a[,4], maxColorValue=255) m <- merge(v[,1:2], a[, c(1,5)], by=1) r <- rast(x, 1) r[m$id] <- m$group - 1 coltab(r) <- a$cols if (filename != "") { r <- writeRaster(r, filename, overwrite, ...) } r } ) */ terra/src/progress.hpp0000644000175000017500000000561214201035750014666 0ustar nileshnilesh/* * progress.hpp * * A Front-end class for InterruptableProgressMonitor. * * Author: karl.forner@gmail.com * */ #ifndef _RcppProgress_PROGRESS_HPP #define _RcppProgress_PROGRESS_HPP #include "progress_monitor_interruptable.hpp" #include "progress_bar_simple.hpp" // e.g. for Rf_error #include class Progress { public: /** * * Main constructor * @param max the expected number of tasks to perform * @param display_progress whether to display a progress bar in the console * @param pb the ProgressBar instance to use */ Progress( unsigned long max, bool display_progress = true, ProgressBar& pb = default_progress_bar() ) { //if ( monitor_singleton() != 0) { // something is wrong, two simultaneous Progress monitoring //Rf_error("ERROR: there is already an InterruptableProgressMonitor instance defined"); //} monitor_singleton() = new InterruptableProgressMonitor(max, display_progress, pb); } ~Progress() { cleanup(); } public: // ==== USER INTERFACE ===== /** * cleanup * * should normally not be called, unless a something bad happens ( * a process/thread that crashes). * */ void cleanup() { if (monitor_singleton() != 0) delete monitor_singleton(); monitor_singleton() = 0; } /** * increment the current progress. * * This method should preferably be used intead of update in a OpenMP context. * * Iff called by the master thread, it will also update the display if needed * * @param amount the number of newly performed tasks to report * * @return false iff the computation is aborted */ bool increment(unsigned long amount=1) { return monitor().increment(amount); } /** * set the current progress indicator * * Iff called by the master thread, it will also update the display if needed * * @param current the total number of performed tasks so far (by all threads) * * @return false iff the computation is aborted */ bool update(unsigned long current) { return monitor().update(current); } /** * return if the computation has been aborted. * N.B: do not perform any check by itselfd */ bool is_aborted() const { return monitor().is_aborted(); } /** * check that the no interruption has been requested and return the current status * * Iff called by the master thread, it will check for R-user level interruption. * * @return true iff the computation is aborted */ static bool check_abort() { return monitor().check_abort(); } private: static InterruptableProgressMonitor*& monitor_singleton() { static InterruptableProgressMonitor* p = 0; return p; } // trick to provide a default static member in a header file static SimpleProgressBar& default_progress_bar() { static SimpleProgressBar pb; pb.reset(); return pb; } public: // ==== OTHER PUBLIC INTERFACE ===== static InterruptableProgressMonitor& monitor() { return *monitor_singleton(); } }; #endif terra/src/distRaster.cpp0000644000175000017500000017473514201035750015156 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include "spatRaster.h" #include "distance.h" #include #include #include "geodesic.h" #include "recycle.h" #include "math_utils.h" #include "vecmath.h" void shortDistPoints(std::vector &d, const std::vector &x, const std::vector &y, const std::vector &px, const std::vector &py, const bool& lonlat, const double &lindist) { if (lonlat) { distanceToNearest_lonlat(d, x, y, px, py); } else { distanceToNearest_plane(d, x, y, px, py, lindist); } } void shortDirectPoints(std::vector &d, const std::vector &x, const std::vector &y, const std::vector &px, const std::vector &py, const bool& lonlat, bool &from, bool °rees) { if (lonlat) { directionToNearest_lonlat(d, x, y, px, py, degrees, from); } else { directionToNearest_plane(d, x, y, px, py, degrees, from); } } SpatRaster SpatRaster::disdir_vector_rasterize(SpatVector p, bool align_points, bool distance, bool from, bool degrees, SpatOptions &opt) { SpatRaster out = geometry(); if (source[0].srs.wkt == "") { out.setError("CRS not defined"); return(out); } double m = source[0].srs.to_meter(); m = std::isnan(m) ? 1 : m; SpatRaster x; std::string gtype = p.type(); std::vector> pxy; if (gtype == "points") { pxy = p.coordinates(); if (pxy.size() == 0) { out.setError("no locations to compute from"); return(out); } if (align_points) { std::vector cells = cellFromXY(pxy[0], pxy[1]); cells.erase(std::unique(cells.begin(), cells.end()), cells.end()); pxy = xyFromCell(cells); } } else { SpatOptions ops(opt); std::vector feats(p.size(), 1) ; x = out.rasterize(p, "", feats, NAN, false, false, false, false, false, ops); if (gtype == "polygons") { std::string etype = "inner"; x = x.edges(false, etype, 8, 0, ops); } p = x.as_points(false, true, opt); pxy = p.coordinates(); } if (pxy.size() == 0) { out.setError("no locations to compute from"); return(out); } bool lonlat = is_lonlat(); // m == 0 //double torad = 0.0174532925199433; //if (!lonlat) { // for (size_t i=0; i v, cells; cells.resize(out.bs.nrows[i] * nc) ; std::iota(cells.begin(), cells.end(), out.bs.row[i] * nc); if (gtype == "points") { readBlock(v, out.bs, i); for (size_t j=0; j> xy = xyFromCell(cells); if (distance) { for (double& d : cells) d = 0; shortDistPoints(cells, xy[0], xy[1], pxy[0], pxy[1], lonlat, m); } else { for (double& d : cells) d = NAN; shortDirectPoints(cells, xy[0], xy[1], pxy[0], pxy[1], lonlat, from, degrees); } if (!out.writeBlock(cells, i)) return out; } out.writeStop(); readStop(); return(out); } SpatRaster SpatRaster::distance_vector(SpatVector p, SpatOptions &opt) { SpatRaster out = geometry(); if (source[0].srs.wkt == "") { out.setError("CRS not defined"); return(out); } double m = source[0].srs.to_meter(); m = std::isnan(m) ? 1 : m; if (p.size() == 0) { out.setError("no locations to compute distance from"); return(out); } p = p.aggregate(false); // bool lonlat = is_lonlat(); // m == 0 unsigned nc = ncol(); if (!out.writeStart(opt)) { readStop(); return out; } std::vector cells; for (size_t i = 0; i < out.bs.n; i++) { double s = out.bs.row[i] * nc; cells.resize(out.bs.nrows[i] * nc) ; std::iota(cells.begin(), cells.end(), s); std::vector> xy = xyFromCell(cells); SpatVector pv(xy[0], xy[1], points, ""); pv.srs = p.srs; std::vector d = p.distance(pv, false); if (p.hasError()) { out.setError(p.getError()); out.writeStop(); return(out); } if (!out.writeBlock(d, i)) return out; } out.writeStop(); return(out); } SpatRaster SpatRaster::distance(SpatOptions &opt) { SpatRaster out = geometry(1); if (!hasValues()) { out.setError("SpatRaster has no values"); return out; } SpatOptions ops(opt); size_t nl = nlyr(); if (nl > 1) { std::vector nms = getNames(); if (ops.names.size() == nms.size()) { nms = opt.names; } out.source.resize(nl); for (unsigned i=0; i lyr = {i}; SpatRaster r = subset(lyr, ops); ops.names = {nms[i]}; r = r.distance(ops); out.source[i] = r.source[0]; } if (opt.get_filename() != "") { out = out.writeRaster(opt); } return out; } out = edges(false, "inner", 8, NAN, ops); SpatVector p = out.as_points(false, true, ops); if (p.size() == 0) { return out.init({0}, opt); } out = disdir_vector_rasterize(p, false, true, false, false, opt); return out; } SpatRaster SpatRaster::direction(bool from, bool degrees, SpatOptions &opt) { SpatRaster out = geometry(1); if (!hasValues()) { out.setError("SpatRaster has no values"); return out; } SpatOptions ops(opt); size_t nl = nlyr(); if (nl > 1) { out.source.resize(nl); std::vector nms = getNames(); if (ops.names.size() == nms.size()) { nms = opt.names; } for (unsigned i=0; i lyr = {i}; SpatRaster r = subset(lyr, ops); ops.names = {nms[i]}; r = r.direction(from, degrees, ops); out.source[i] = r.source[0]; } if (opt.get_filename() != "") { out = out.writeRaster(opt); } return out; } out = edges(false, "inner", 8, NAN, ops); SpatVector p = out.as_points(false, true, opt); if (p.size() == 0) { out.setError("no cells to compute direction from or to"); return(out); } out = disdir_vector_rasterize(p, false, false, from, degrees, opt); return out; } std::vector SpatVector::distance(bool sequential) { std::vector d; if (srs.is_empty()) { setError("crs not defined"); return(d); } double m = srs.to_meter(); m = std::isnan(m) ? 1 : m; bool lonlat = is_lonlat(); // m == 0 // if ((!lonlat) || (gtype != "points")) { std::string gtype = type(); if (gtype != "points") { d = geos_distance(sequential); if ((!lonlat) && (m != 1)) { for (double &i : d) i *= m; } return d; } else { if (sequential) { std::vector> p = coordinates(); size_t n = p[0].size(); d.reserve(n); d.push_back(0); n -= 1; if (lonlat) { for (size_t i=0; i> p = coordinates(); if (lonlat) { for (size_t i=0; i<(s-1); i++) { for (size_t j=(i+1); j SpatVector::distance(SpatVector x, bool pairwise) { std::vector d; if (srs.is_empty() || x.srs.is_empty()) { setError("SRS not defined"); return(d); } if (! srs.is_same(x.srs, false) ) { setError("SRS do not match"); return(d); } size_t s = size(); size_t sx = x.size(); if ((s == 0) || (sx == 0)) { setError("empty SpatVector"); return(d); } if (pairwise && (s != sx ) && (s > 1) && (sx > 1)) { setError("Can only do pairwise distance if geometries match, or if one is a single geometry"); return(d); } double m = srs.to_meter(); m = std::isnan(m) ? 1 : m; bool lonlat = is_lonlat(); std::string gtype = type(); std::string xtype = x.type(); /* int ispts = (gtype == "points") + (xtype == "points"); if ((lonlat) && (ispts == 1)) { if (xtype == "points") { return linedistLonLat(x); } else { return x.linedistLonLat(*this); } } */ if ((!lonlat) || (gtype != "points") || (xtype != "points")) { d = geos_distance(x, pairwise); if ((!lonlat) && (m != 1)) { for (double &i : d) i *= m; } return d; } std::vector> p = coordinates(); std::vector> px = x.coordinates(); /* recycling, not a good idea. if (pairwise) { if (s < sx) { recycle(p[0], sx); recycle(p[1], sx); s = sx; } else if (s > sx) { recycle(px[0], s); recycle(px[1], s); sx = s; } } */ size_t n = pairwise ? std::max(s,sx) : s*sx; d.resize(n); if (pairwise) { if (s == sx) { if (lonlat) { for (size_t i = 0; i < s; i++) { d[i] = distance_lonlat(p[0][i], p[1][i], px[0][i], px[1][i]); } } else { // not reached for (size_t i = 0; i < s; i++) { d[i] = distance_plane(p[0][i], p[1][i], px[0][i], px[1][i]) * m; } } } else if (s == 1) { // to avoid recycling. if (lonlat) { for (size_t i = 0; i < sx; i++) { d[i] = distance_lonlat(p[0][0], p[1][0], px[0][i], px[1][i]); } } else { // not reached for (size_t i = 0; i < sx; i++) { d[i] = distance_plane(p[0][0], p[1][0], px[0][i], px[1][i]) * m; } } } else { // if (sx == 1) { if (lonlat) { for (size_t i = 0; i < s; i++) { d[i] = distance_lonlat(p[0][i], p[1][i], px[0][0], px[1][0]); } } else { // not reached for (size_t i = 0; i < s; i++) { d[i] = distance_plane(p[0][i], p[1][i], px[0][0], px[1][0]) * m; } } } } else { if (lonlat) { for (size_t i=0; i &d) { d.erase(std::remove_if(d.begin(), d.end(), [](const double& v) { return std::isnan(v); }), d.end()); std::sort(d.begin(), d.end()); return d.size() > 0 ? d[1] : NAN; } std::vector cost_dist_planar(double source, std::vector &v, std::vector &above, std::vector res, size_t nr, size_t nc, double lindist) { double dx = res[0] * lindist; double dy = res[1] * lindist; double dxy = sqrt(dx * dx + dy *dy); std::vector dist(v.size(), 0); std::vector cd; //top to bottom //left to right //first cell, no cell left of it if (std::isnan(v[0]) ) { dist[0] = NAN; } else if (v[0] != source) { cd = {v[0], above[0] * dy}; dist[0] = minCostDist(cd); } for (size_t i=1; i -1; i--) { // other cells on first row if (!std::isnan(v[i])) { if (v[i] == source) { dist[i] = 0; } else { cd = { v[i], dist[i+1], above[i+1] * dxy, above[i] * dy, dist[i] }; dist[i] = minCostDist(cd); } } } for (size_t r=1; r=(r*nc); i--) { if (std::isnan(v[i])) { cd = { dist[i], dist[i+1], dist[i-nc], dist[i-nc+1] }; dist[i] = minCostDist(cd); } } } size_t off = (nr-1) * nc; above = std::vector(dist.begin()+off, dist.end()); return dist; } SpatRaster SpatRaster::costDistance(double to, SpatOptions &opt) { SpatRaster out = geometry(1); if (!hasValues()) { out.setError("cannot compute distance for a raster with no values"); return out; } SpatOptions ops(opt); if (nlyr() > 1) { std::vector lyr = {0}; out = subset(lyr, ops); out = out.costDistance(to, opt); out.addWarning("distance computations are only done for the first input layer"); return out; } //bool isgeo = out.islonlat double m = source[0].srs.to_meter(); m = std::isnan(m) ? 1 : m; std::vector res = resolution(); SpatRaster first = out.geometry(); std::string tempfile = ""; std::vector above(ncol(), std::numeric_limits::infinity()); std::vector d, v, vv; if (!readStart()) { out.setError(getError()); return(out); } std::string filename = opt.get_filename(); opt.set_filenames({""}); if (!first.writeStart(opt)) { return first; } // bool lonlat = is_lonlat(); size_t nc = ncol(); for (size_t i = 0; i < first.bs.n; i++) { readBlock(v, first.bs, i); // if (lonlat) { // double lat = yFromRow(first.bs.row[i]); // d = broom_dist_geo(v, above, res, first.bs.nrows[i], nc, lat, -1); // } else { d = cost_dist_planar(to, v, above, res, first.bs.nrows[i], nc, m); // } if (!first.writeValues(d, first.bs.row[i], first.bs.nrows[i])) return first; } first.writeStop(); if (!first.readStart()) { out.setError(first.getError()); return(out); } opt.set_filenames({filename}); above = std::vector(ncol(), std::numeric_limits::infinity()); if (!out.writeStart(opt)) { readStop(); return out; } for (int i = out.bs.n; i>0; i--) { readBlock(v, out.bs, i-1); std::reverse(v.begin(), v.end()); // if (lonlat) { // double lat = yFromRow(out.bs.row[i-1] + out.bs.nrows[i-1] - 1); // d = broom_dist_geo(v, above, res, out.bs.nrows[i-1], nc, lat, 1); // } else { d = cost_dist_planar(to, v, above, res, out.bs.nrows[i-1], nc, m); // } first.readBlock(vv, out.bs, i-1); std::transform (d.rbegin(), d.rend(), vv.begin(), vv.begin(), [](double a, double b) {return std::min(a,b);}); if (!out.writeValues(vv, out.bs.row[i-1], out.bs.nrows[i-1])) return out; } out.writeStop(); readStop(); first.readStop(); return(out); } std::vector broom_dist_planar(std::vector &v, std::vector &above, std::vector res, size_t nr, size_t nc, double lindist) { double dx = res[0] * lindist; double dy = res[1] * lindist; double dxy = sqrt(dx * dx + dy *dy); std::vector dist(v.size(), 0); //left to right //first cell, no cell left of it if ( std::isnan(v[0]) ) { dist[0] = above[0] + dy; } //first row, no row above it, use "above" for (size_t i=1; i -1; i--) { if (std::isnan(v[i])) { dist[i] = std::min(std::min(std::min(dist[i+1] + dx, above[i+1] + dxy), above[i] + dy), dist[i]); } } // other rows for (size_t r=1; r=(r*nc); i--) { if (std::isnan(v[i])) { dist[i] = std::min(std::min(std::min(dist[i], dist[i+1] + dx), dist[i-nc] + dy), dist[i-nc+1] + dxy); } } } size_t off = (nr-1) * nc; above = std::vector(dist.begin()+off, dist.end()); return dist; } inline double minNArm(const double &a, const double &b) { if (std::isnan(a)) return b; if (std::isnan(b)) return a; return std::min(a, b); } inline void DxDxy(const double &lat, const int &row, double xres, double yres, const int &dir, double &dx, double &dy, double &dxy) { double rlat = lat + row * yres * dir; dx = distance_lonlat(0, rlat , xres, rlat); yres *= -dir; dy = distance_lonlat(0, rlat, 0, rlat+yres); dxy = distance_lonlat(0, rlat, xres, rlat+yres); dy = std::isnan(dy) ? std::numeric_limits::infinity() : dy; dxy = std::isnan(dxy) ? std::numeric_limits::infinity() : dxy; } std::vector broom_dist_geo(std::vector &v, std::vector &above, std::vector res, size_t nr, size_t nc, double lat, double latdir) { // double dy = distance_lonlat(0, 0, 0, res[1]); double dx, dy, dxy; std::vector dist(v.size(), 0); //top to bottom //left to right DxDxy(lat, 0, res[0], res[1], latdir, dx, dy, dxy); //first cell, no cell left of it if ( std::isnan(v[0]) ) { dist[0] = above[0] + dy; } //first row, no row above it, use "above" for (size_t i=1; i -1; i--) { if (std::isnan(v[i])) { dist[i] = std::min(std::min(std::min(dist[i+1] + dx, above[i+1] + dxy), above[i] + dy), dist[i]); } } // other rows for (size_t r=1; r=(r*nc); i--) { if (std::isnan(v[i])) { dist[i] = std::min(std::min(std::min(dist[i], dist[i+1] + dx), dist[i-nc] + dy), dist[i-nc+1] + dxy); } } } size_t off = (nr-1) * nc; above = std::vector(dist.begin()+off, dist.end()); return dist; } std::vector broom_dist_geo_global(std::vector &v, std::vector &above, std::vector res, size_t nr, size_t nc, double lat, double latdir) { // double dy = distance_lonlat(0, 0, 0, res[1]); double dx, dy, dxy; std::vector dist(v.size(), 0); size_t stopnc = nc - 1; //top to bottom //left to right DxDxy(lat, 0, res[0], res[1], latdir, dx, dy, dxy); //first cell, no cell left of it if ( std::isnan(v[0]) ) { dist[0] = std::min(above[0] + dy, above[stopnc] + dxy); } //first row, no row above it, use "above" for (size_t i=1; i -1; i--) { if (std::isnan(v[i])) { dist[i] = std::min(std::min(std::min(std::min(dist[i+1] + dx, above[i+1] + dxy), above[i] + dy), dist[i]), dist[stopnc] + dx * (i+1)); } } // other rows for (size_t r=1; r=end; i--) { if (std::isnan(v[i])) { // dist[i] = std::min(std::min(std::min(dist[i], dist[i+1] + dx), dist[i-nc] + dy), dist[i-nc+1] + dxy); dist[i] = std::min(std::min(std::min(std::min(dist[i], dist[i+1] + dx), dist[i-nc] + dy), dist[i-nc+1] + dxy), dist[start] + dx * (i-end)); } } } size_t off = (nr-1) * nc; above = std::vector(dist.begin()+off, dist.end()); return dist; } SpatRaster SpatRaster::gridDistance(SpatOptions &opt) { SpatRaster out = geometry(1); if (!hasValues()) { out.setError("cannot compute distance for a raster with no values"); return out; } SpatOptions ops(opt); size_t nl = nlyr(); if (nl > 1) { out.source.resize(nl); for (unsigned i=0; i lyr = {i}; SpatRaster r = subset(lyr, ops); r = r.gridDistance(ops); out.source[i] = r.source[0]; } if (opt.get_filename() != "") { out = out.writeRaster(opt); } return out; } bool lonlat = is_lonlat(); bool global = is_global_lonlat(); double m = source[0].srs.to_meter(); m = std::isnan(m) ? 1 : m; if (lonlat) { m = 1; } std::vector res = resolution(); SpatRaster first = out.geometry(); std::string tempfile = ""; std::vector above(ncol(), std::numeric_limits::infinity()); std::vector d, v, vv; if (!readStart()) { out.setError(getError()); return(out); } std::string filename = opt.get_filename(); opt.set_filenames({""}); if (!first.writeStart(opt)) { return first; } size_t nc = ncol(); for (size_t i = 0; i < first.bs.n; i++) { readBlock(v, first.bs, i); if (lonlat) { double lat = yFromRow(first.bs.row[i]); if (global) { d = broom_dist_geo_global(v, above, res, first.bs.nrows[i], nc, lat, -1); } else { d = broom_dist_geo(v, above, res, first.bs.nrows[i], nc, lat, -1); } } else { d = broom_dist_planar(v, above, res, first.bs.nrows[i], nc, m); } if (!first.writeValues(d, first.bs.row[i], first.bs.nrows[i])) return first; } first.writeStop(); if (!first.readStart()) { out.setError(first.getError()); return(out); } opt.set_filenames({filename}); above = std::vector(ncol(), std::numeric_limits::infinity()); if (!out.writeStart(opt)) { readStop(); return out; } for (int i = out.bs.n; i>0; i--) { readBlock(v, out.bs, i-1); std::reverse(v.begin(), v.end()); if (lonlat) { double lat = yFromRow(out.bs.row[i-1] + out.bs.nrows[i-1] - 1); if (global) { d = broom_dist_geo_global(v, above, res, out.bs.nrows[i-1], nc, lat, 1); } else { d = broom_dist_geo(v, above, res, out.bs.nrows[i-1], nc, lat, 1); } } else { d = broom_dist_planar(v, above, res, out.bs.nrows[i-1], nc, m); } first.readBlock(vv, out.bs, i-1); std::transform (d.rbegin(), d.rend(), vv.begin(), vv.begin(), [](double a, double b) {return std::min(a,b);}); if (!out.writeValues(vv, out.bs.row[i-1], out.bs.nrows[i-1])) return out; /* std::reverse(d.begin(), d.end()); if (!out.writeValues(d, out.bs.row[i-1], out.bs.nrows[i-1])) return out; */ } out.writeStop(); readStop(); //first.readStop(); //first.source.push_back(out.source[0]); //return first; return(out); } std::vector do_edge(const std::vector &d, const size_t nrow, const size_t ncol, const bool classes, const bool inner, const unsigned dirs, double falseval) { size_t n = nrow * ncol; std::vector val(n, falseval); int r[8] = { -1,0,0,1 , -1,-1,1,1}; int c[8] = { 0,-1,1,0 , -1,1,-1,1}; if (!classes) { if (inner) { // inner for (size_t i = 1; i < (nrow-1); i++) { for (size_t j = 1; j < (ncol-1); j++) { size_t cell = i*ncol+j; val[cell] = NAN; if ( !std::isnan(d[cell])) { val[cell] = falseval; for (size_t k=0; k< dirs; k++) { if ( std::isnan(d[cell + r[k] * ncol + c[k]])) { val[cell] = 1; break; } } } } } } else { //outer for (size_t i = 1; i < (nrow-1); i++) { for (size_t j = 1; j < (ncol-1); j++) { size_t cell = i*ncol+j; val[cell] = falseval; if (std::isnan(d[cell])) { val[cell] = NAN; for (size_t k=0; k < dirs; k++) { if ( !std::isnan(d[cell+ r[k] * ncol + c[k] ])) { val[cell] = 1; break; } } } } } } } else { // by class for (size_t i = 1; i < (nrow-1); i++) { for (size_t j = 1; j < (ncol-1); j++) { size_t cell = i*ncol+j; double test = d[cell+r[0]*ncol+c[0]]; val[cell] = std::isnan(test) ? NAN : falseval; for (size_t k=1; k &v, size_t nr, size_t nc, bool rowbefore, bool rowafter, bool cols) { if (rowbefore) { v.insert(v.begin(), v.begin(), v.begin()+nc); nr++; } if (rowafter) { v.insert(v.end(), v.end()-nc, v.end()); nr++; } if (cols) { for (size_t i=0; i &v, size_t nr, size_t nc, bool rows, bool cols) { if (rows) { v.erase(v.begin(), v.begin()+nc); v.erase(v.end()-nc, v.end()); nr -= 2; } if (cols) { nc -= 2; for (size_t i=0; i 1) { std::vector lyr = {0}; SpatOptions ops(opt); out = subset(lyr, ops); out = out.edges(classes, type, directions, falseval, opt); out.addWarning("boundary detection is only done for the first layer"); return out; } if (!hasValues()) { out.setError("SpatRaster has no values"); return out; } if ((directions != 4) && (directions != 8)) { out.setError("directions should be 4 or 8"); return(out); } if ((type != "inner") && (type != "outer")) { out.setError("directions should be 'inner' or 'outer'"); return(out); } bool inner = type == "inner"; size_t nc = ncol(); size_t nr = nrow(); if (!readStart()) { out.setError(getError()); return(out); } opt.minrows = 2; if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i = 0; i < out.bs.n; i++) { std::vector v; //bool before = false; //bool after = false; if (i == 0) { if (out.bs.n == 1) { readValues(v, out.bs.row[i], out.bs.nrows[i], 0, nc); addrowcol(v, nr, nc, true, true, true); } else { readValues(v, out.bs.row[i], out.bs.nrows[i]+1, 0, nc); addrowcol(v, nr, nc, true, false, true); //after = true; } } else { //before = true; if (i == out.bs.n) { readValues(v, out.bs.row[i]-1, out.bs.nrows[i]+1, 0, nc); addrowcol(v, nr, nc, false, true, true); } else { readValues(v, out.bs.row[i]-1, out.bs.nrows[i]+2, 0, nc); addrowcol(v, nr, nc, false, false, true); //after = true; } } //before, after, std::vector vv = do_edge(v, out.bs.nrows[i]+2, nc+2, classes, inner, directions, falseval); striprowcol(vv, out.bs.nrows[i]+2, nc+2, true, true); if (!out.writeBlock(vv, i)) return out; } out.writeStop(); readStop(); return(out); } SpatRaster SpatRaster::buffer(double d, SpatOptions &opt) { SpatRaster out = geometry(1); if (!hasValues()) { out.setError("SpatRaster has no values"); return out; } if (d <= 0) { out.setError("buffer size <= 0; nothing to compute"); return out; } SpatOptions ops(opt); if (nlyr() > 1) { std::vector lyr = {0}; out = subset(lyr, ops); out = out.buffer(d, opt); out.addWarning("buffer computations are only done for the first input layer"); return out; } std::string etype = "inner"; SpatRaster e = edges(false, etype, 8, 0, ops); SpatVector p = e.as_points(false, true, opt); out = out.disdir_vector_rasterize(p, false, true, false, false, ops); out = out.arith(d, "<=", false, opt); return out; } void SpatVector::fix_lonlat_overflow() { if (! ((extent.xmin < -180) || (extent.xmax > 180))) { return; } SpatExtent world(-180, 180, -90, 90); std::string vt = type(); if (vt == "points") { for (size_t i=0; i 180) { geoms[i].parts[j].x[k] -= 360; } } } } } else { SpatExtent east(-360, -180, -180, 180); SpatExtent west(180, 360, -180, 180); for (size_t i=0; i 180) { SpatVector v(geoms[i]); if (geoms[i].extent.xmin >= 180) { v = v.shift(-360, 0); } else { SpatVector add = v.crop(west); add = add.shift(-360, 0); v = v.crop(world); v.geoms[i].addPart(add.geoms[0].parts[0]); } replaceGeom(v.geoms[0], i); } } } if ((extent.ymax > 90) || (extent.ymin < -90)) { SpatVector out = crop(world); geoms = out.geoms; extent = out.extent; df = out.df; srs = out.srs; } return; } void sort_unique_2d(std::vector &x, std::vector &y) { std::vector> v(x.size()); for (size_t i=0; i &a, const std::vector &b) { return a[0] < b[0];}); v.erase(std::unique(v.begin(), v.end()), v.end()); x.resize(v.size()); y.resize(v.size()); for (size_t i=0; i &x, const std::vector &y) { SpatPart p(x, y); double minx = vmin(x, false); double maxx = vmax(x, false); // need a better check but this should work for all normal cases if ((minx < -170) && (maxx > 170)) { for (size_t i=0; i d, unsigned quadsegs, bool no_multipolygons) { SpatVector out; std::string vt = type(); if (vt != "points") { out.setError("geometry must be points"); return out; } size_t npts = size(); size_t n = quadsegs * 4; double step = 360.0 / n; SpatGeom g(polygons); g.addPart(SpatPart(0, 0)); std::vector> xy = coordinates(); if (is_lonlat()) { std::vector brng(n); for (size_t i=0; i 90) || (xy[1][i] < -90)) { out.addGeom(SpatGeom(polygons)); } else { std::vector ptx; std::vector pty; ptx.reserve(n); pty.reserve(n); geod_inverse(&gd, xy[1][i], xy[0][i], 90, xy[0][i], &s12, &azi, &azi2); bool npole = s12 < d[i]; geod_inverse(&gd, xy[1][i], xy[0][i], -90, xy[0][i], &s12, &azi, &azi2); bool spole = s12 < d[i]; if (npole && spole) { ptx = std::vector {-180, 0, 180, 180, 180, 0, -180, -180}; pty = std::vector { 90, 90, 90, 0, -90, -90, -90, 0}; npole = false; spole = false; } else { for (size_t j=0; j < n; j++) { geod_direct(&gd, xy[1][i], xy[0][i], brng[j], d[i], &lat, &lon, &azi); ptx.push_back(lon); pty.push_back(lat); } } if (npole) { sort_unique_2d(ptx, pty); if (ptx[ptx.size()-1] < 180) { ptx.push_back(180); pty.push_back(pty[pty.size()-1]); } ptx.push_back(180); pty.push_back(90); ptx.push_back(-180); pty.push_back(90); if (ptx[0] > -180) { ptx.push_back(-180); pty.push_back(pty[0]); } ptx.push_back(ptx[0]); pty.push_back(pty[0]); g.reSetPart(SpatPart(ptx, pty)); out.addGeom(g); } else if (spole) { sort_unique_2d(ptx, pty); if (ptx[ptx.size()-1] < 180) { ptx.push_back(180); pty.push_back(pty[pty.size()-1]); } ptx.push_back(180); pty.push_back(-90); ptx.push_back(-180); pty.push_back(-90); if (ptx[0] > -180) { ptx.push_back(-180); pty.push_back(pty[0]); } ptx.push_back(ptx[0]); pty.push_back(pty[0]); g.reSetPart(SpatPart(ptx, pty)); out.addGeom(g); } else { ptx.push_back(ptx[0]); pty.push_back(pty[0]); bool split = fix_date_line(g, ptx, pty); if (split & no_multipolygons) { for (size_t j=0; j cosb(n); std::vector sinb(n); std::vector px(n+1); std::vector py(n+1); for (size_t i=0; i &lon, const std::vector &lat) { struct geod_polygon p; geod_polygon_init(&p, 0); size_t n = lat.size(); for (size_t i=0; i < n; i++) { //double lat = lat[i] > 90 ? 90 : lat[i] < -90 ? -90 : lat[i]; // for #397 double flat = lat[i] < -90 ? -90 : lat[i]; geod_polygon_addpoint(&g, &p, flat, lon[i]); } double area, P; geod_polygon_compute(&g, &p, 0, 1, &area, &P); return(area < 0 ? -area : area); } double area_polygon_plane(std::vector x, std::vector y) { // based on http://paulbourke.net/geometry/polygonmesh/source1.c size_t n = x.size(); double area = x[n-1] * y[0]; area -= y[n-1] * x[0]; for (size_t i=0; i < (n-1); i++) { area += x[i] * y[i+1]; area -= x[i+1] * y[i]; } area /= 2; return(area < 0 ? -area : area); } double area_lonlat(geod_geodesic &g, const SpatGeom &geom) { double area = 0; if (geom.gtype != polygons) return area; for (size_t i=0; i SpatVector::area(std::string unit, bool transform, std::vector mask) { size_t s = size(); size_t m = mask.size(); bool domask = false; if (m > 0) { if (s != mask.size()) { addWarning("mask size is not correct"); } else { domask = true; } } std::vector ar; ar.reserve(s); std::vector ss {"m", "km", "ha"}; if (std::find(ss.begin(), ss.end(), unit) == ss.end()) { setError("invalid unit"); return {NAN}; } double adj = unit == "m" ? 1 : unit == "km" ? 1000000 : 10000; if (srs.wkt == "") { addWarning("unknown CRS. Results can be wrong"); if (domask) { for (size_t i=0; i &lon, const std::vector &lat) { size_t n = lat.size(); double length = 0; for (size_t i=1; i < n; i++) { length += distance_lonlat(lon[i-1], lat[i-1], lon[i], lat[i]); } return (length); } double length_line_plane(std::vector x, std::vector y) { size_t n = x.size(); double length = 0; for (size_t i=1; i SpatVector::length() { size_t s = size(); std::vector r; r.reserve(s); double m = srs.to_meter(); m = std::isnan(m) ? 1 : m; if (m == 0) { struct geod_geodesic g; double a = 6378137; double f = 1 / 298.257223563; geod_init(&g, a, f); for (size_t i=0; i f {"m", "km", "ha"}; if (std::find(f.begin(), f.end(), unit) == f.end()) { out.setError("invalid unit"); return out; } if (opt.names.size() == 0) { opt.names = {"area"}; } bool lonlat = is_lonlat(); SpatOptions mopt(opt); if (mask) { if (!hasValues()) { mask = false; } else { mopt.filenames = opt.filenames; opt = SpatOptions(opt); } } if (lonlat) { bool disagg = false; SpatOptions xopt(opt); SpatExtent extent = getExtent(); if ((out.ncol() == 1) && ((extent.xmax - extent.xmin) > 180)) { disagg = true; std::vector fact = {1,2}; out = out.disaggregate(fact, xopt); } if (!out.writeStart(opt)) { return out; } SpatExtent e = {extent.xmin, extent.xmin+out.xres(), extent.ymin, extent.ymax}; SpatRaster onecol = out.crop(e, "near", xopt); SpatVector p = onecol.as_polygons(false, false, false, false, xopt); if (p.hasError()) { out.setError(p.getError()); return out; } std::vector a = p.area(unit, true, {}); size_t nc = out.ncol(); for (size_t i = 0; i < out.bs.n; i++) { std::vector v; v.reserve(out.bs.nrows[i] * nc); size_t r = out.bs.row[i]; for (size_t j=0; j fact = {1,2}; opt.overwrite=true; out = tmp.aggregate(fact, "sum", true, opt); } else { out.writeStop(); } } else { if (!out.writeStart(opt)) { return out; } if (transform) { SpatExtent extent = getExtent(); double dy = yres() / 2; SpatOptions popt(opt); for (size_t i = 0; i < out.bs.n; i++) { double ymax = yFromRow(out.bs.row[i]) + dy; double ymin = yFromRow(out.bs.row[i] + out.bs.nrows[i]-1) - dy; SpatExtent e = {extent.xmin, extent.xmax, ymin, ymax}; SpatRaster onechunk = out.crop(e, "near", popt); SpatVector p = onechunk.as_polygons(false, false, false, false, popt); //std::vector cells(onechunk.ncell()); //std::iota (cells.begin(), cells.end(), 0); //onechunk.setValues(cells); //SpatVector p = onechunk.as_polygons(false, true, false, false, popt); std::vector v; v = p.area(unit, true, {}); if (!out.writeBlock(v, i)) return out; } } else { double u = unit == "m" ? 1 : unit == "km" ? 1000000 : 10000; double m = out.source[0].srs.to_meter(); double a = std::isnan(m) ? 1 : m; a *= xres() * yres() / u; for (size_t i = 0; i < out.bs.n; i++) { std::vector v(out.bs.nrows[i]*ncol(), a); if (!out.writeBlock(v, i)) return out; } } out.writeStop(); } if (mask) { out = out.mask(*this, false, NAN, NAN, mopt); } return(out); } std::vector SpatRaster::sum_area(std::string unit, bool transform, SpatOptions &opt) { if (source[0].srs.wkt == "") { setError("empty CRS"); return {NAN}; } std::vector f {"m", "km", "ha"}; if (std::find(f.begin(), f.end(), unit) == f.end()) { setError("invalid unit"); return {NAN}; } std::vector out(nlyr(), 0); if (transform) { //avoid very large polygon objects opt.set_memfrac(std::max(0.1, opt.get_memfrac()/2)); } BlockSize bs = getBlockSize(opt); if (!readStart()) { std::vector err(nlyr(), -1); return(err); } if (is_lonlat()) { SpatRaster x = geometry(1); SpatExtent extent = x.getExtent(); if ((x.ncol() == 1) && ((extent.xmax - extent.xmin) > 180)) { std::vector fact= {1,2}; x = x.disaggregate(fact, opt); } size_t nc = x.ncol(); SpatExtent e = {extent.xmin, extent.xmin+x.xres(), extent.ymin, extent.ymax}; SpatRaster onecol = x.crop(e, "near", opt); SpatVector p = onecol.as_polygons(false, false, false, false, opt); std::vector ar = p.area(unit, true, {}); if (!hasValues()) { out.resize(1); for (size_t i=0; i v; readValues(v, bs.row[i], bs.nrows[i], 0, ncol()); size_t blockoff = bs.nrows[i] * nc; for (size_t lyr=0; lyr v = p.area(unit, true, {}); out[0] += accumulate(v.begin(), v.end(), 0.0); } } else { for (size_t i=0; i par = p.area(unit, true, {}); std::vector v; readValues(v, bs.row[i], bs.nrows[i], 0, ncol()); unsigned off = bs.nrows[i] * ncol() ; for (size_t lyr=0; lyr v; readValues(v, bs.row[i], bs.nrows[i], 0, ncol()); unsigned off = bs.nrows[i] * ncol() ; for (size_t lyr=0; lyr> SpatRaster::area_by_value(SpatOptions &opt) { double m = source[0].srs.to_meter(); m = std::isnan(m) ? 1 : m; if (m != 0) { double ar = xres() * yres() * m * m; std::vector> f = freq(true, false, 0, opt); for (size_t i=0; i> out(nlyr()); return out; } } void do_flowdir(std::vector &val, std::vector const &d, size_t nrow, size_t ncol, double dx, double dy, unsigned seed, bool before, bool after) { if (!before) { val.resize(val.size() + ncol, NAN); } std::vector r = {0, 0, 0, 0, 0, 0, 0, 0}; std::vector p = {1, 2, 4, 8, 16, 32, 64, 128}; // pow(2, j) double dxy = sqrt(dx * dx + dy * dy); std::default_random_engine generator(seed); std::uniform_int_distribution<> U(0, 1); for (size_t row=1; row< (nrow-1); row++) { val.push_back(NAN); for (size_t col=1; col< (ncol-1); col++) { size_t i = row * ncol + col; if (!std::isnan(d[i])) { r[0] = (d[i] - d[i+1]) / dx; r[1] = (d[i] - d[i+1+ncol]) / dxy; r[2] = (d[i] - d[i+ncol]) / dy; r[3] = (d[i] - d[i-1+ncol]) / dxy; r[4] = (d[i] - d[i-1]) / dx; r[5] = (d[i] - d[i-1-ncol]) / dxy; r[6] = (d[i] - d[i-ncol]) / dy; r[7] = (d[i] - d[i+1-ncol]) / dxy; // using the lowest neighbor, even if it is higher than the focal cell. double dmin = r[0]; int k = 0; for (size_t j=1; j<8; j++) { if (r[j] > dmin) { dmin = r[j]; k = j; } else if (r[j] == dmin) { if (U(generator)) { dmin = r[j]; k = j; } } } val.push_back( p[k] ); } else { val.push_back( NAN ); } } val.push_back(NAN); } if (!after) { val.resize(val.size() + ncol, NAN); } } void do_TRI(std::vector &val, std::vector const &d, size_t nrow, size_t ncol, bool before, bool after) { if (!before) { val.resize(val.size() + ncol, NAN); } for (size_t row=1; row< (nrow-1); row++) { val.push_back(NAN); for (size_t col=1; col< (ncol-1); col++) { size_t i = row * ncol + col; val.push_back( (fabs(d[i-1-ncol]-d[i]) + fabs(d[i-1]-d[i]) + fabs(d[i-1+ncol]-d[i]) + fabs(d[i-ncol]-d[i]) + fabs(d[i+ncol]-d[i]) + fabs(d[i+1-ncol]-d[i]) + fabs(d[i+1]-d[i]) + fabs(d[i+1+ncol]-d[i])) / 8 ); } val.push_back(NAN); } if (!after) { val.resize(val.size() + ncol, NAN); } } void do_TPI(std::vector &val, const std::vector &d, const size_t nrow, const size_t ncol, bool before, bool after) { if (!before) { val.resize(val.size() + ncol, NAN); } for (size_t row=1; row< (nrow-1); row++) { val.push_back(NAN); for (size_t col=1; col< (ncol-1); col++) { size_t i = row * ncol + col; val.push_back( d[i] - (d[i-1-ncol] + d[i-1] + d[i-1+ncol] + d[i-ncol] + d[i+ncol] + d[i+1-ncol] + d[i+1] + d[i+1+ncol]) / 8 ); } val.push_back(NAN); } /* if (expand) { for (size_t i=1; i < (ncol-1); i++) { val[i+add] = d[i] - (d[i-1] + d[i-1+ncol] + d[i+ncol] + d[i+1] + d[i+1+ncol]) / 5; size_t j = i+(nrow-1) * ncol; val[j+add] = d[j] - (d[j-1-ncol] + d[j-1] + d[j-ncol] + d[j+1-ncol] + d[j+1]) / 5; } for (size_t row=1; row< (nrow-1); row++) { size_t i = row * ncol; val[i+add] = d[i] - (d[i-ncol] + d[i+ncol] + d[i+1-ncol] + d[i+1] + d[i+1+ncol]) / 5; i += ncol - 1; val[i+add] = d[i] - (d[i-ncol] + d[i] + d[i+ncol] + d[i-ncol]) / 5; } size_t i = 0; val[i+add] = d[i] - (d[i+ncol] + d[i+1] + d[i+1+ncol]) / 3; i = ncol-1; val[i+add] = d[i] - (d[i+ncol] + d[i-1] + d[i-1+ncol]) / 3; i = (nrow-1)*ncol; val[i+add] = d[i] - (d[i-ncol] + d[i+1] + d[i+1-ncol]) / 3; i = (nrow*ncol)-1; val[i+add] = d[i] - (d[i-ncol] + d[i-1] + d[i-1-ncol]) / 3; } */ if (!after) { val.resize(val.size() + ncol, NAN); } } void do_roughness(std::vector &val, const std::vector &d, size_t nrow, size_t ncol, bool before, bool after) { if (!before) { val.resize(val.size() + ncol, NAN); } int incol = ncol; int a[9] = { -1-incol, -1, -1+incol, -incol, 0, incol, 1-incol, 1, 1+incol }; double min, max, v; for (size_t row=1; row< (nrow-1); row++) { val.push_back(NAN); for (size_t col=1; col< (ncol-1); col++) { size_t i = row * ncol + col; min = d[i + a[0]]; max = d[i + a[0]]; for (size_t j = 1; j < 9; j++) { v = d[i + a[j]]; if (v > max) { max = v; } else if (v < min) { min = v; } } val.push_back(max - min); } val.push_back(NAN); } if (!after) { val.resize(val.size() + ncol, NAN); } } #ifndef M_PI #define M_PI (3.14159265358979323846) #endif void to_degrees(std::vector& x, size_t start) { double adj = 180 / M_PI; for (size_t i=start; i &val, const std::vector &d, unsigned ngb, unsigned nrow, unsigned ncol, double dx, double dy, bool geo, std::vector &gy, bool degrees, bool before, bool after) { size_t start = val.size(); if (!before) { val.resize(start + ncol, NAN); } std::vector ddx; if (geo) { ddx.resize(nrow); for (size_t i=0; i &val, const std::vector &d, unsigned ngb, unsigned nrow, unsigned ncol, double dx, double dy, bool geo, std::vector &gy, bool degrees, bool before, bool after) { size_t start = val.size(); if (!before) { val.resize(start + ncol, NAN); } std::vector ddx; if (geo) { ddx.resize(nrow); for (size_t i=0; i v, unsigned neighbors, bool degrees, unsigned seed, SpatOptions &opt) { //TPI, TRI, aspect, flowdir, slope, roughness //std::sort(v.begin(), v.end()); //v.erase(std::unique(v.begin(), v.end()), v.end()); SpatRaster out = geometry(v.size()); out.setNames(v); if (nlyr() > 1) { out.setError("terrain needs a single layer object"); return out; } bool aspslope = false; std::vector f {"TPI", "TRI", "aspect", "flowdir", "slope", "roughness"}; for (size_t i=0; i val(out.bs.nrows[i] * nc, NAN); if (!out.writeBlock(val, i)) return out; } return out; } std::vector y; for (size_t i = 0; i < out.bs.n; i++) { std::vector d; bool before= false; bool after = false; size_t rrow = out.bs.row[i]; size_t rnrw = out.bs.nrows[i]; if (i > 0) { rrow--; rnrw++; before=true; } if ((out.bs.row[i] + out.bs.nrows[i]) < nrow()) { rnrw++; after = true; } readValues(d, rrow, rnrw, 0, nc); if (lonlat && aspslope) { std::vector rows(rnrw); std::iota(rows.begin(), rows.end(), rrow); y = yFromRow(rows); yr = distHaversine(0, 0, 0, yres()); } std::vector val; val.reserve(out.bs.nrows[i] * ncol() * v.size()); for (size_t j =0; j. #include #include "spatRasterMultiple.h" #include "recycle.h" #include "math_utils.h" #include "vecmath.h" //#include "modal.h" /* // need to take care of NAs here. OK for NAN, but not for int types //template //void operator+(std::vector& a, const std::vector& b) { void operator+(std::vector& a, const std::vector& b) { std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::plus()); } //template void operator-(std::vector& a, const std::vector& b) { std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::minus()); } //template void operator/(std::vector& a, const std::vector& b) { std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::divides()); } //template void operator*(std::vector& a, const std::vector& b) { std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::multiplies()); } */ //template void operator%(std::vector& a, const std::vector& b) { // std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::modulus()); for (size_t i=0; i void operator==(std::vector& a, const std::vector& b) { // std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::equal_to()); for (size_t i=0; i void operator!=(std::vector& a, const std::vector& b) { // std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::not_equal_to()); for (size_t i=0; i void operator>=(std::vector& a, const std::vector& b) { // std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::greater_equal()); for (size_t i=0; i= b[i]; } } } //template void operator<=(std::vector& a, const std::vector& b) { // std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::less_equal()); for (size_t i=0; i void operator>(std::vector& a, const std::vector& b) { // std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::greater()); for (size_t i=0; i b[i]; } } } //template void operator<(std::vector& a, const std::vector& b) { // std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::less()); for (size_t i=0; i void power(std::vector& a, const std::vector& b) { for (size_t i=0; i f {"==", "!=", ">", "<", ">=", "<="}; logical = std::find(f.begin(), f.end(), oper) != f.end(); f = {"+", "-", "*", "^", "/", "%"}; return (logical || (std::find(f.begin(), f.end(), oper) != f.end())); } SpatRaster SpatRaster::arith(SpatRaster x, std::string oper, SpatOptions &opt) { size_t nl = std::max(nlyr(), x.nlyr()); SpatRaster out = geometry(nl); if (!(hasValues() & x.hasValues())) { out.setError("raster has no values"); // or warn and treat as NA? return out; } bool logical = false; if (!smooth_operator(oper, logical)) { out.setError("unknown arith function"); return out; } if (logical) { out.setValueType(3); } if (!out.compare_geom(x, false, true, opt.get_tolerance())) { return(out); } if (!readStart()) { out.setError(getError()); return(out); } if (!x.readStart()) { out.setError(x.getError()); return(out); } if (!out.writeStart(opt)) { readStop(); x.readStop(); return out; } for (size_t i = 0; i < out.bs.n; i++) { std::vector a, b; readBlock(a, out.bs, i); x.readBlock(b, out.bs, i); recycle(a,b); if (oper == "+") { std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::plus()); } else if (oper == "-") { std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::minus()); } else if (oper == "*") { std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::multiplies()); } else if (oper == "/") { std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::divides()); } else if (oper == "^") { power(a, b); } else if (oper == "%") { a % b; } else if (oper == "==") { a == b; } else if (oper == "!=") { a != b; } else if (oper == ">=") { a >= b; } else if (oper == "<=") { a <= b; } else if (oper == ">") { a > b; } else if (oper == "<") { a < b; } if (!out.writeBlock(a, i)) return out; } out.writeStop(); readStop(); x.readStop(); return(out); } SpatRaster SpatRaster::arith(double x, std::string oper, bool reverse, SpatOptions &opt) { SpatRaster out = geometry(nlyr()); if (!hasValues()) { out.setError("raster has no values"); // or warn and treat as NA? return out; } bool logical; if (!smooth_operator(oper, logical)) { out.setError("unknown arith function"); return out; } if (logical) { out.setValueType(3); } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i = 0; i < out.bs.n; i++) { std::vector a; readBlock(a, out.bs, i); if (std::isnan(x)) { for(double& d : a) d = NAN; } else if (oper == "+") { for(double& d : a) d += x; } else if (oper == "-") { if (reverse) { for(double& d : a) d = x - d; } else { for(double& d : a) d -= x; } } else if (oper == "*") { for(double& d : a) d *= x; } else if (oper == "/") { if (reverse) { for(double& d : a) d = x / d; } else { for(double& d : a) d /= x; } } else if (oper == "^") { if (reverse) { for(double& d : a) d = std::pow(x, d); } else { for(double& d : a) d = std::pow(d, x); } } else if (oper == "%") { if (reverse) { for (size_t i=0; i=") { if (reverse) { for(double& d : a) if (!std::isnan(d)) d = x >= d; } else { for(double& d : a) if (!std::isnan(d)) d = d >= x; } } else if (oper == "<=") { if (reverse) { for(double& d : a) if (!std::isnan(d)) d = x <= d; } else { for(double& d : a) if (!std::isnan(d)) d = d <= x; } } else if (oper == ">") { if (reverse) { for(double& d : a) if (!std::isnan(d)) d = x > d; } else { for(double& d : a) if (!std::isnan(d)) d = d > x; } } else if (oper == "<") { if (reverse) { for(double& d : a) if (!std::isnan(d)) d = x < d; } else { for(double& d : a) if (!std::isnan(d)) d = d < x; } } else { // stop } if (!out.writeBlock(a, i)) return out; } out.writeStop(); readStop(); return(out); } SpatRaster SpatRaster::is_true(SpatOptions &opt) { return arith(1, "==", false, opt); } SpatRaster SpatRaster::is_false(SpatOptions &opt) { return arith(1, "!=", false, opt); } SpatRaster SpatRaster::arith(std::vector x, std::string oper, bool reverse, SpatOptions &opt) { if (x.size() == 0) { SpatRaster out; out.setError("cannot compute with nothing"); return out; } if (!hasValues()) { SpatRaster out; out.setError("raster has no values"); // or warn and treat as NA? return out; } if (x.size() == 1) { return(arith(x[0], oper, reverse, opt)); } unsigned innl = nlyr(); unsigned outnl = innl; if (x.size() > innl) { outnl = x.size(); } SpatRaster out = geometry(outnl); bool logical=false; if (!smooth_operator(oper, logical)) { out.setError("unknown arith function"); return out; } if (logical) { out.setValueType(3); } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } unsigned nc = ncol(); recycle(x, outnl); for (size_t i = 0; i < out.bs.n; i++) { std::vector v; readBlock(v, out.bs, i); if (outnl > innl) { recycle(v, outnl * out.bs.nrows[i] * nc); } std::vector vv; unsigned off = out.bs.nrows[i] * nc; for (size_t j=0; j a(v.begin()+s, v.begin()+s+off); if (std::isnan(x[j])) { for(double& d : a) d = NAN; } else if (oper == "+") { for(double& d : a) d += x[j]; } else if (oper == "-") { if (reverse) { for(double& d : a) d = x[j] - d; } else { for(double& d : a) d -= x[j]; } } else if (oper == "*") { for(double& d : a) d *= x[j]; } else if (oper == "/") { if (reverse) { for(double& d : a) d = x[j] / d; } else { for(double& d : a) d /= x[j]; } } else if (oper == "^") { if (reverse) { for(double& d : a) d = std::pow(x[j], d); } else { for(double& d : a) d = std::pow(d, x[j]); } } else if (oper == "%") { if (reverse) { for (size_t k=0; k=") { if (reverse) { for(double& d : a) if (!std::isnan(d)) d = x[j] >= d; } else { for(double& d : a) if (!std::isnan(d)) d = d >= x[j]; } } else if (oper == "<=") { if (reverse) { for(double& d : a) if (!std::isnan(d)) d = x[j] <= d; } else { for(double& d : a) if (!std::isnan(d)) d = d <= x[j]; } } else if (oper == ">") { if (reverse) { for(double& d : a) if (!std::isnan(d)) d = x[j] > d; } else { for(double& d : a) if (!std::isnan(d)) d = d > x[j]; } } else if (oper == "<") { if (reverse) { for(double& d : a) if (!std::isnan(d)) d = x[j] < d; } else { for(double& d : a) if (!std::isnan(d)) d = d < x[j]; } } else { // stop } std::copy(a.begin(), a.end(), v.begin()+s); } if (!out.writeBlock(v, i)) return out; } out.writeStop(); readStop(); return(out); } template int sign(T value) { return (T(0) < value) - (value < T(0)); } double dabs(double x) { return (x < 0 ? -1 * x : x); } SpatRaster SpatRaster::math(std::string fun, SpatOptions &opt) { SpatRaster out = geometry(); if (!hasValues()) return out; std::vector f {"abs", "ceiling", "floor", "trunc", "sign"}; bool is_int = std::find(f.begin(), f.end(), fun) != f.end(); if (is_int) out.setValueType(1); f = {"abs", "sqrt", "ceiling", "floor", "trunc", "log", "log10", "log2", "log1p", "exp", "expm1", "sign"}; if ((!is_int) && std::find(f.begin(), f.end(), fun) == f.end()) { out.setError("unknown math function"); return out; } std::function mathFun; if (fun == "sqrt") { mathFun = static_cast(sqrt); } else if (fun == "abs") { mathFun = dabs; } else if (fun == "log") { mathFun = static_cast(log); } else if (fun == "log2") { mathFun = static_cast(log2); } else if (fun == "log10") { mathFun = static_cast(log10); } else if (fun == "log1p") { mathFun = static_cast(log1p); } else if (fun == "exp") { mathFun = static_cast(exp); } else if (fun == "expm1") { mathFun = static_cast(expm1); } else if (fun == "sign") { mathFun = sign; } else if (fun == "ceiling") { mathFun = static_cast(ceil); } else if (fun == "floor") { mathFun = static_cast(floor); } else if (fun == "trunc") { mathFun = static_cast(trunc); } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i = 0; i < out.bs.n; i++) { std::vector a; readBlock(a, out.bs, i); for(double& d : a) if (!std::isnan(d)) d = mathFun(d); if (!out.writeBlock(a, i)) return out; } out.writeStop(); readStop(); return(out); } SpatRaster SpatRaster::math2(std::string fun, unsigned digits, SpatOptions &opt) { SpatRaster out = geometry(); if (!hasValues()) return out; std::vector f {"round", "signif"}; if (std::find(f.begin(), f.end(), fun) == f.end()) { out.setError("unknown math2 function"); return out; } if (digits == 0) out.setValueType(1); if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i = 0; i < out.bs.n; i++) { std::vector a; readBlock(a, out.bs, i); if (fun == "round") { for(double& d : a) d = roundn(d, digits); } else if (fun == "signif") { for(double& d : a) if (!std::isnan(d)) d = signif(d, digits); } if (!out.writeBlock(a, i)) return out; } out.writeStop(); readStop(); return(out); } double sin_pi(double &x) { return sin(x * M_PI); } double cos_pi(double &x) { return sin(x * M_PI); } double tan_pi(double &x) { return sin(x * M_PI); } SpatRaster SpatRaster::trig(std::string fun, SpatOptions &opt) { SpatRaster out = geometry(); if (!hasValues()) return out; std::vector f {"acos", "asin", "atan", "cos", "sin", "tan", "acosh", "asinh", "atanh", "cosh", "cospi", "sinh", "sinpi", "tanh", "tanpi"}; if (std::find(f.begin(), f.end(), fun) == f.end()) { out.setError("unknown trig function"); return out; } std::function trigFun; if (fun == "sin") { trigFun = static_cast(sin); } else if (fun == "cos") { trigFun = static_cast(cos); } else if (fun == "tan") { trigFun = static_cast(tan); } else if (fun == "asin") { trigFun = static_cast(asin); } else if (fun == "acos") { trigFun = static_cast(acos); } else if (fun == "atan") { trigFun = static_cast(atan); } else if (fun == "sinh") { trigFun = static_cast(sinh); } else if (fun == "cosh") { trigFun = static_cast(cosh); } else if (fun == "tanh") { trigFun = static_cast(tanh); } else if (fun == "asinh") { trigFun = static_cast(asinh); } else if (fun == "acosh") { trigFun = static_cast(acosh); } else if (fun == "atanh") { trigFun = static_cast(atanh); } else if (fun == "sinpi") { trigFun = sin_pi; } else if (fun == "cospi") { trigFun = cos_pi; } else if (fun == "tanpi") { trigFun = tan_pi; } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i = 0; i < out.bs.n; i++) { std::vector a; readValues(a, out.bs.row[i], out.bs.nrows[i], 0, ncol()); for (double& d : a) if (!std::isnan(d)) d = trigFun(d); if (!out.writeBlock(a, i)) return out; } out.writeStop(); readStop(); return(out); } SpatRaster SpatRaster::atan_2(SpatRaster x, SpatOptions &opt) { SpatRaster out = geometry(); if (!hasValues()) return out; if (!readStart()) { out.setError(getError()); return(out); } if (!x.readStart()) { out.setError(x.getError()); return(out); } if (!out.writeStart(opt)) { readStop(); x.readStop(); return out; } for (size_t i = 0; i < out.bs.n; i++) { std::vector a, b; readValues(a, out.bs.row[i], out.bs.nrows[i], 0, ncol()); x.readValues(b, out.bs.row[i], out.bs.nrows[i], 0, ncol()); recycle(a, b); std::vector d(a.size()); for (size_t i=0; i std::vector operator&(const std::vector& a, const std::vector& b) { std::vector result; result.reserve(a.size()); std::transform(a.begin(), a.end(), b.begin(), std::back_inserter(result), std::logical_and()); for (size_t i=0; i std::vector operator|(const std::vector& a, const std::vector& b) { std::vector result; result.reserve(a.size()); std::transform(a.begin(), a.end(), b.begin(), std::back_inserter(result), std::logical_or()); for (size_t i=0; i a; readBlock(a, out.bs, i); for (size_t j=0; j f {"&", "|"}; if (std::find(f.begin(), f.end(), oper) == f.end()) { out.setError("unknown logic function"); return out; } if (!out.compare_geom(x, true, false, opt.get_tolerance())) { return(out); } if (!readStart()) { out.setError(getError()); return(out); } if (!x.readStart()) { out.setError(x.getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i = 0; i < out.bs.n; i++) { std::vector a; readBlock(a, out.bs, i); std::vector b; x.readBlock(b, out.bs, i); if (oper == "&") { a = a & b; } else if (oper == "|") { a = a | b; } else { // stop } if (!out.writeBlock(a, i)) return out; } out.writeStop(); readStop(); x.readStop(); return(out); } SpatRaster SpatRaster::logic(bool x, std::string oper, SpatOptions &opt) { SpatRaster out = geometry(); if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } std::vector v, m; for (size_t i = 0; i < out.bs.n; i++) { std::vector a; readBlock(a, out.bs, i); if (std::isnan(x)) { for(double& d : a) d = NAN; } else if (oper == "&") { for(double& d : a) d = (d==1) & x; } else if (oper == "|") { for(double& d : a) d = (d==1) | x; } else if (oper == "istrue") { for(double& d : a) d = d==1 ? 1 : 0; } else if (oper == "isfalse") { for(double& d : a) d = d!=1 ? 1 : 0; } else { out.setError("unknown operator: " + oper); return out; } if (!out.writeBlock(a, i)) return out; } out.writeStop(); readStop(); return(out); } SpatRaster SpatRaster::cum(std::string fun, bool narm, SpatOptions &opt) { SpatRaster out = geometry(); std::vector f {"sum", "prod", "min", "max"}; if (std::find(f.begin(), f.end(), fun) == f.end()) { out.setError("unknown cum function"); return out; } if (!hasValues()) { // out.setError("raster has no values"); return out; } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } unsigned nl = out.nlyr(); std::vector v(nl); unsigned nc; for (size_t i = 0; i < out.bs.n; i++) { std::vector a; readBlock(a, out.bs, i); nc = out.bs.nrows[i] * out.ncol(); for (size_t j=0; j v, bool narm) { double m = vmean(v, narm); for (double& d : v) d = pow(d - m, 2); m = vmean(v, narm); return sqrt(m); } SpatRaster SpatRaster::summary_numb(std::string fun, std::vector add, bool narm, SpatOptions &opt) { SpatRaster out = geometry(1); if (!hasValues()) { return out; } if (fun == "range") { return range(add, narm, opt); } out.source[0].names[0] = fun; std::function&, bool)> sumFun; if (fun == "std") { sumFun = vstdev; } else { if (!haveFun(fun)) { out.setError("unknown function argument"); return out; } sumFun = getFun(fun); } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } unsigned nl = nlyr(); std::vector v(nl); if (add.size() > 0) v.insert( v.end(), add.begin(), add.end() ); for (size_t i = 0; i < out.bs.n; i++) { std::vector a; readBlock(a, out.bs, i); unsigned nc = out.bs.nrows[i] * out.ncol(); std::vector b(nc); for (size_t j=0; j add; return summary_numb(fun, add, narm, opt); } SpatRaster SpatRaster::modal(std::vector add, std::string ties, bool narm, SpatOptions &opt) { SpatRaster out = geometry(1); out.source[0].names[0] = "modal" ; if (!hasValues()) { return out; } std::vector f {"lowest", "highest", "first", "random", "NA"}; //std::vector::iterator it; auto it = std::find(f.begin(), f.end(), ties); if (it == f.end()) { out.setError("unknown ties choice"); return out; } size_t ities = std::distance(f.begin(), it); if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } uint32_t seed = 1; std::default_random_engine rgen(seed); std::uniform_real_distribution dist (0.0,1.0); unsigned nl = nlyr(); std::vector v(nl); v.insert( v.end(), add.begin(), add.end() ); for (size_t i = 0; i < out.bs.n; i++) { std::vector a; readBlock(a, out.bs, i); unsigned nc = out.bs.nrows[i] * out.ncol(); std::vector b(nc); for (size_t j=0; j add, bool narm, SpatOptions &opt) { SpatRaster out = geometry(2); out.source[0].names.resize(2); out.source[0].names[0] = "range_min" ; out.source[0].names[1] = "range_max" ; if (!hasValues()) { return out; } if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } unsigned nl = nlyr(); std::vector v(nl); v.insert( v.end(), add.begin(), add.end() ); for (size_t i = 0; i < out.bs.n; i++) { std::vector a; readBlock(a, out.bs, i); unsigned nc = out.bs.nrows[i] * out.ncol(); std::vector b(nc * 2); for (size_t j=0; j rng = vrange(v, narm); b[j] = rng[0]; b[j+nc] = rng[1]; } if (!out.writeBlock(b, i)) return out; } out.writeStop(); readStop(); return(out); } SpatRaster SpatRasterStack::summary_numb(std::string fun, std::vector add, bool narm, SpatOptions &opt) { std::vector vnl = nlyr(); unsigned nl = vmax(vnl, false); SpatRaster out = ds[0].geometry(nl); unsigned ns = nsds(); if (fun == "range") { out.setError("parallel range not implemented, use min and max"); return out; } if (!ds[0].hasValues()) { return out; } std::function&, bool)> sumFun; if (fun == "std") { sumFun = vstdev; } else { if (!haveFun(fun)) { out.setError("unknown function argument"); return out; } sumFun = getFun(fun); } for (size_t i=0; i < ns; i++) { if (!ds[i].readStart()) { out.setError(ds[i].getError()); return(out); } } if (!out.writeStart(opt)) { readStop(); return out; } std::vector v(ns); if (add.size() > 0) v.insert( v.end(), add.begin(), add.end() ); std::vector> a(ns); for (size_t i=0; i < out.bs.n; i++) { unsigned nc = out.bs.nrows[i] * out.ncol() * nl; for (size_t j=0; j < ns; j++) { ds[j].readBlock(a[j], out.bs, i); recycle(a[j], nc); } std::vector b(nc); for (size_t j=0; j add; return summary_numb(fun, add, narm, opt); } SpatRaster SpatRaster::isnan(SpatOptions &opt) { SpatRaster out = geometry(); out.setValueType(3); if (!hasValues()) return out; if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i=0; i v; readBlock(v, out.bs, i); for (double &d : v) d = std::isnan(d); if (!out.writeBlock(v, i)) return out; } readStop(); out.writeStop(); return(out); } SpatRaster SpatRaster::isnotnan(SpatOptions &opt) { SpatRaster out = geometry(); out.setValueType(3); if (!hasValues()) return out; if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i=0; i v; readBlock(v, out.bs, i); for (double &d : v) d = ! std::isnan(d); if (!out.writeBlock(v, i)) return out; } readStop(); out.writeStop(); return(out); } SpatRaster SpatRaster::isfinite(SpatOptions &opt) { SpatRaster out = geometry(); out.setValueType(3); if (!hasValues()) return out; if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i=0; i v; readBlock(v, out.bs, i); for (double &d : v) d = std::isfinite(d); if (!out.writeBlock(v, i)) return out; } readStop(); out.writeStop(); return(out); } SpatRaster SpatRaster::isinfinite(SpatOptions &opt) { SpatRaster out = geometry(); out.setValueType(3); if (!hasValues()) return out; if (!readStart()) { out.setError(getError()); return(out); } if (!out.writeStart(opt)) { readStop(); return out; } for (size_t i=0; i v; readBlock(v, out.bs, i); for (double &d : v) d = std::isinf(d); if (!out.writeBlock(v, i)) return out; } readStop(); out.writeStop(); return(out); } terra/src/write_ogr.cpp0000644000175000017500000003205214201626141015014 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include "spatVector.h" #include "string_utils.h" #ifdef useGDAL #include "file_utils.h" #include "ogrsf_frmts.h" GDALDataset* SpatVector::write_ogr(std::string filename, std::string lyrname, std::string driver, bool append, bool overwrite, std::vector options) { GDALDataset *poDS = NULL; if (filename != "") { if (file_exists(filename) && (!overwrite) && (!append)) { setError("file exists. Use 'overwrite=TRUE' to overwrite it"); return(poDS); } if (nrow() == 0) { setError("no geometries to write"); return(poDS); } } if (append) { poDS = static_cast(GDALOpenEx(filename.c_str(), GDAL_OF_VECTOR | GDAL_OF_UPDATE, NULL, NULL, NULL )); std::vector lyrnms; size_t n = poDS->GetLayerCount(); for (size_t i=0; iGetLayer(i); if (poLayer != NULL) { lyrnms.push_back((std::string)poLayer->GetName()); } } if (is_in_vector(lyrname, lyrnms)) { if (!overwrite) { setError("layer exists. Use 'overwrite=TRUE' to overwrite it"); return(poDS); } else { options.push_back("OVERWRITE=YES"); } } } else { GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName( driver.c_str() ); if( poDriver == NULL ) { setError( driver + " driver not available"); return poDS; } char **papszMetadata; papszMetadata = poDriver->GetMetadata(); if (!CSLFetchBoolean( papszMetadata, GDAL_DCAP_VECTOR, FALSE)) { setError(driver + " is not a vector format"); return poDS; } if (!CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE)) { setError("cannot create a "+ driver + " dataset"); return poDS; } poDS = poDriver->Create(filename.c_str(), 0, 0, 0, GDT_Unknown, NULL ); } if( poDS == NULL ) { setError("Creation of output dataset failed" ); return poDS; } OGRwkbGeometryType wkb; SpatGeomType geomtype = geoms[0].gtype; if (geomtype == points) { wkb = wkbPoint; } else if (geomtype == lines) { wkb = wkbMultiLineString; } else if (geomtype == polygons) { wkb = wkbMultiPolygon; } else { setError("this geometry type is not supported: " + type()); return poDS; } std::string s = srs.wkt; OGRSpatialReference *SRS = NULL; if (s != "") { SRS = new OGRSpatialReference; OGRErr err = SRS->SetFromUserInput(s.c_str()); #if GDAL_VERSION_NUM >= 2050000 SRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); #endif if (err != OGRERR_NONE) { setError("crs error"); delete SRS; return poDS; } } size_t nGroupTransactions = 0; OGRLayer *poLayer; char** papszOptions = NULL; if (options.size() > 0) { for (size_t i=0; i gopt = strsplit(options[i], "="); if (gopt.size() == 2) { if (gopt[0] == "nGroupTransactions") { try { nGroupTransactions = std::stoi(gopt[1]); } catch (std::invalid_argument &e) { nGroupTransactions = 0; } } else { papszOptions = CSLSetNameValue(papszOptions, gopt[0].c_str(), gopt[1].c_str() ); } } } // papszOptions = CSLSetNameValue( papszOptions, "ENCODING", "UTF-8" ); } poLayer = poDS->CreateLayer(lyrname.c_str(), SRS, wkb, papszOptions); CSLDestroy(papszOptions); if( poLayer == NULL ) { setError( "Layer creation failed" ); return poDS; } // if (SRS != NULL) SRS->Release(); if (SRS != NULL) OSRDestroySpatialReference(SRS); std::vector nms = get_names(); std::vector tps = df.get_datatypes(); OGRFieldType otype; int nfields = nms.size(); size_t ngeoms = size(); for (int i=0; iCreateField( &oField ) != OGRERR_NONE ) { setError( "Field creation failed for: " + nms[i]); return poDS; } } // use a single transaction as in sf // makes a big difference for gpkg by avoiding many INSERTs bool can_do_transaction = poDS->TestCapability(ODsCTransactions); // == TRUE); bool transaction = false; if (can_do_transaction) { transaction = (poDS->StartTransaction() == OGRERR_NONE); if (! transaction) { setError("transaction failed"); return poDS; } } // chunks if (nGroupTransactions == 0) { nGroupTransactions = 50000; } size_t gcntr = 0; for (size_t i=0; iGetLayerDefn() ); for (int j=0; jSetField(j, df.getDvalue(i, j)); } else if (tps[j] == "long") { poFeature->SetField(j, (GIntBig)df.getIvalue(i, j)); } else { poFeature->SetField(j, df.getSvalue(i, j).c_str()); } } //r++; // points -- also need to do multi-points OGRPoint pt; if (wkb == wkbPoint) { if (!std::isnan(geoms[i].parts[0].x[0])) { pt.setX( geoms[i].parts[0].x[0] ); pt.setY( geoms[i].parts[0].y[0] ); } poFeature->SetGeometry( &pt ); // lines } else if (wkb == wkbMultiLineString) { OGRMultiLineString poGeom; for (size_t j=0; jSetGeometry( &poGeom ) != OGRERR_NONE) { setError("cannot set geometry"); return poDS; } // polygons } else if (wkb == wkbMultiPolygon) { SpatGeom g = getGeom(i); OGRMultiPolygon poGeom; for (size_t j=0; jSetGeometry( &poGeom ) != OGRERR_NONE) { setError("cannot set geometry"); return poDS; } } else { setError("Only points, lines and polygons are currently supported"); return poDS; } if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE ) { setError("Failed to create feature"); return poDS; } OGRFeature::DestroyFeature( poFeature ); gcntr++; if (transaction && (gcntr == nGroupTransactions)) { if (poDS->CommitTransaction() != OGRERR_NONE) { poDS->RollbackTransaction(); setError("transaction commit failed"); } gcntr = 0; transaction = (poDS->StartTransaction() == OGRERR_NONE); if (! transaction) { setError("transaction failed"); return poDS; } } } if (transaction && (gcntr>0) && (poDS->CommitTransaction() != OGRERR_NONE)) { poDS->RollbackTransaction(); setError("transaction commit failed"); } return poDS; } bool SpatVector::write(std::string filename, std::string lyrname, std::string driver, bool append, bool overwrite, std::vector options) { if (nrow() == 0) { addWarning("nothing to write"); return false; } GDALDataset *poDS = write_ogr(filename, lyrname, driver, append, overwrite, options); if (poDS != NULL) GDALClose( poDS ); if (hasError()) { return false; } return true; } GDALDataset* SpatVector::GDAL_ds() { return write_ogr("", "layer", "Memory", false, true, std::vector()); } #include bool SpatDataFrame::write_dbf(std::string filename, bool overwrite, SpatOptions &opt) { // filename is here "raster.tif" // to write "raster.tif.vat.dbf" if (filename != "") { if (file_exists(filename) & (!overwrite)) { setError("file exists. Use 'overwrite=TRUE' to overwrite it"); return(false); } if (nrow() == 0) { setError("nothing to write"); return(false); } } std::string fbase = tempFile(opt.get_tempdir(), opt.pid, ""); std::string f = fbase + ".shp"; GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName( "ESRI Shapefile" ); GDALDataset *poDS = NULL; poDS = poDriver->Create(f.c_str(), 0, 0, 0, GDT_Unknown, NULL ); if( poDS == NULL ) { setError("Creation of output dataset failed" ); return false; } OGRwkbGeometryType wkb = wkbPoint; OGRSpatialReference *SRS = NULL; OGRLayer *poLayer; poLayer = poDS->CreateLayer("dbf", SRS, wkb, NULL ); if( poLayer == NULL ) { setError( "Layer creation failed" ); return false; } std::vector nms = get_names(); std::vector tps = get_datatypes(); OGRFieldType otype; int nfields = nms.size(); for (int i=0; iCreateField( &oField ) != OGRERR_NONE ) { setError( "Field creation failed for: " + nms[i]); return false; } } for (size_t i=0; iGetLayerDefn() ); for (int j=0; jSetField(j, getDvalue(i, j)); } else if (tps[j] == "long") { poFeature->SetField(j, (GIntBig) getIvalue(i, j)); } else { poFeature->SetField(j, getSvalue(i, j).c_str()); } } OGRPoint pt; pt.setX( 0.0 ); pt.setY( 0.0 ); poFeature->SetGeometry( &pt ); if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE ) { setError("Failed to create feature"); return false; } OGRFeature::DestroyFeature( poFeature ); } GDALClose( poDS ); f = fbase + ".dbf"; filename += ".vat.dbf"; // c++17 has file_copy std::ifstream src(f.c_str(), std::ios::binary); std::ofstream dst(filename.c_str(), std::ios::binary); dst << src.rdbuf(); filename.erase(filename.length()-3); filename += "cpg"; std::ofstream cpg; cpg.open (filename.c_str()); cpg << "UTF-8"; cpg.close(); return true; } bool SpatVector::delete_layers(std::string filename, std::vector layers, bool return_error) { if (filename == "") { setError("empty filename"); return false; } if (!file_exists(filename)) { setError("file does not exist"); return false; } if (layers.size() == 0) return(true); GDALDataset *poDS = static_cast(GDALOpenEx(filename.c_str(), GDAL_OF_VECTOR | GDAL_OF_UPDATE, NULL, NULL, NULL )); if( poDS == NULL ) { setError("Cannot open or update this dataset" ); return false; } std::string fails; size_t n = poDS->GetLayerCount(); for (int i =(n-1); i > 0; i--) { size_t m = layers.size(); if (m == 0) break; OGRLayer *poLayer = poDS->GetLayer(i); if (poLayer == NULL) continue; std::string lname = poLayer->GetName(); for (size_t j=0; jDeleteLayer(i); if (err == OGRERR_UNSUPPORTED_OPERATION) { setError("Deleting layer not supported for this file (format / driver)"); GDALClose(poDS); return(false); } if (err != OGRERR_NONE) { if (fails.size() > 0) { fails += ", " + layers[j]; } else { fails = layers[j]; } } layers.erase(layers.begin() + j); break; } } } GDALClose(poDS); if (layers.size() > 0) { fails += concatenate(layers, ", "); } if (fails.size() > 0) { if (return_error) { setError("deleting failed for: " + fails); } else { addWarning("deleting failed for: " + fails); } } return true; } #endif terra/src/ram.h0000644000175000017500000000002714201035750013234 0ustar nileshnileshdouble availableRAM(); terra/src/spatTime.h0000644000175000017500000000122714201035750014246 0ustar nileshnilesh#ifndef SPATTIME_GUARD #define SPATTIME_GUARD //#include //#include typedef long long SpatTime_t; std::vector get_date(SpatTime_t x); std::vector getymd(std::string s); SpatTime_t get_time_string(std::string s); SpatTime_t time_from_day(int syear, int smonth, int sday, double ndays); SpatTime_t time_from_day_noleap(int syear, int smonth, int sday, double ndays); SpatTime_t time_from_day_360(int syear, int smonth, int sday, double ndays); SpatTime_t time_from_hour(int syear, int smonth, int sday, double nhours); void hours_to_time(std::vector &time, std::string origin); SpatTime_t parse_time(std::string x); #endif terra/src/spatRaster.h0000644000175000017500000007361614201035750014623 0ustar nileshnilesh// Copyright (c) 2018-2020 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include #include #include "spatVector.h" #ifdef useGDAL #include "gdal_priv.h" #endif #ifdef useRcpp #include // Rcpp::depends(RcppProgress) #include "progress.hpp" #include "progress_bar.hpp" #endif typedef long long int_64; class SpatCategories { public: virtual ~SpatCategories(){} SpatDataFrame d; unsigned index = 0; }; class SpatWindow { public: virtual ~SpatWindow(){} SpatExtent full_extent; size_t full_ncol, full_nrow, off_row, off_col; bool expanded = false; std::vector expand; }; class SpatRasterSource { private: // std::ofstream ofs; public: #ifdef useGDAL GDALDataset* gdalconnection; #if GDAL_VERSION_MAJOR >= 3 && GDAL_VERSION_MINOR >= 1 GDALMDArrayH gdalmdarray; #endif #endif bool open_read=false; bool open_write=false; SpatRasterSource(); virtual ~SpatRasterSource(){} // void fsopen(std::string filename); // bool fswrite(std::vector &v); // void fsclose(); size_t ncol, nrow; unsigned nlyr; unsigned nlyrfile = 0; SpatExtent extent; bool extset=false; bool rotated=false; bool flipped=false; bool hasWindow=false; SpatWindow window; bool multidim = false; size_t m_ndims; std::vector m_dims; std::vector m_dimnames; // std::vector m_dimstart; // std::vector m_dimend; std::vector m_counts; std::vector m_order; std::vector m_subset; bool m_hasNA = false; double m_missing_value; //std::vector crs = std::vector(2, ""); SpatSRS srs; std::vector layers; // layer names std::vector names; // data source (sds) has one "variable name" / long_name std::string source_name; std::string source_name_long; std::vector time; std::string timestep = "seconds"; bool hasTime = false; std::vector depth; std::vector unit; bool hasUnit = false; //std::vector< std::vector values; std::vector values; //std::vector ivalues; //std::vector bvalues; // unsigned char datatype; std::vector blockrows; std::vector blockcols; std::vector hasRange; std::vector range_min; std::vector range_max; // std::vector hasAttributes; // std::vector atts; // std::vector attsIndex; std::vector hasCategories; std::vector cats; std::vector valueType; std::vector hasColors; std::vector cols; bool memory=true; bool hasValues=false; std::string filename; std::string driver; std::string datatype; std::vector open_ops; // user set for reading: bool hasNAflag = false; double NAflag = NAN; std::vector has_scale_offset; std::vector scale; std::vector offset; // std::vector subset(std::vector lyrs); SpatRasterSource subset(std::vector lyrs); // void getValues(std::vector &v, unsigned lyr, SpatOptions &opt); void appendValues(std::vector &v, unsigned lyr); void setRange(); void resize(unsigned n); bool in_order(); bool combine_sources(const SpatRasterSource &x); bool combine(SpatRasterSource &x); bool parameters_changed = false; void set_names_time_ncdf(std::vector metadata, std::vector> bandmeta, std::string &msg); }; class BlockSize { public: virtual ~BlockSize(){} std::vector row; std::vector nrows; unsigned n; }; class SpatRaster { private: std::string copy_driver = ""; std::string copy_filename = ""; std::vector gdal_options; bool compute_stats = true; bool gdal_stats = false; bool gdal_approx = true; bool gdal_minmax = true; protected: SpatExtent window; public: #ifdef useRcpp Progress* pbar; bool progressbar = false; #endif //////////////////////////////////////////////////// // properties and property-like methods for entire object //////////////////////////////////////////////////// std::vector source; BlockSize bs; //BlockSize getBlockSize(unsigned n, double frac, unsigned steps=0); BlockSize getBlockSize(SpatOptions &opt); std::vector mem_needs(SpatOptions &opt); SpatMessages msg; void setError(std::string s) { msg.setError(s); } void addWarning(std::string s) { msg.addWarning(s); } void setMessage(std::string s) { msg.setMessage(s); } bool hasError() { return msg.has_error; } bool hasWarning() { return msg.has_warning; } std::string getWarnings() { return msg.getWarnings();} std::string getError() { return msg.getError();} std::string getMessage() { return msg.getMessage();} //double NA = std::numeric_limits::quiet_NaN(); size_t ncol(); size_t nrow(); SpatExtent getExtent(); void setExtent(SpatExtent e); void setExtent(SpatExtent ext, bool keepRes=false, std::string snap=""); // also set it for sources? SpatVector dense_extent(bool inside, bool geobounds); //std::vector getCRS(); //void setCRS(std::vector _crs); std::string getSRS(std::string x); bool setSRS(std::string crs); bool rgb=false; std::string rgbtype; std::vector rgblyrs; bool setRGB(int r, int g, int b, int alpha, std::string type); std::vector getRGB(); void removeRGB(); /* #ifdef useGDAL bool setSRS(OGRSpatialReference *poSRS, std::string &msg) { #endif */ bool is_lonlat(); bool could_be_lonlat(); bool is_global_lonlat(); std::vector resolution(); SpatRaster setResolution(double xres, double yres); double ncell() { return nrow() * ncol(); } double size() { return ncol() * nrow() * nlyr() ; } double xres(); double yres(); std::vector origin(); unsigned nlyr(); // only no values allowed with a single SpatRasterSource bool hasValues(); std::vector getValues(long lyr, SpatOptions &opt); bool getValuesSource(size_t src, std::vector &out); bool setValues(std::vector &v, SpatOptions &opt); #ifdef useRcpp bool setValuesRcpp(Rcpp::NumericVector &v, SpatOptions &opt); #endif bool replaceCellValues(std::vector &cells, std::vector &v, bool bylyr, SpatOptions &opt); void setRange(SpatOptions &opt); //////////////////////////////////////////////////// // property like methods for RasterSources //////////////////////////////////////////////////// std::vector filenames(); bool isSource(std::string filename); std::vector inMemory(); //////////////////////////////////////////////////// // property like methods for layers //////////////////////////////////////////////////// std::vector hasRange(); std::vector range_min(); std::vector range_max(); std::vector getValueType(); bool setValueType(unsigned char d); std::vector getNames(); bool setNames(std::vector names, bool make_valid=false); std::vector getSourceNames(); bool setSourceNames(std::vector); std::vector getLongSourceNames(); bool setLongSourceNames(std::vector); bool hasTime(); std::vector getTime(); std::string getTimeStep(); std::vector getTimeStr(bool addstep); bool setTime(std::vector time, std::string step); std::vector getDepth(); bool setDepth(std::vector depths); bool hasUnit(); std::vector getUnit(); bool setUnit(std::vector units); bool setNAflag(std::vector flag); std::vector getNAflag(); //////////////////////////////////////////////////// // constructors //////////////////////////////////////////////////// SpatRaster(); SpatRaster(unsigned nr, unsigned nc, unsigned nl, SpatExtent ext, std::string crs); SpatRaster(std::vector rcl, std::vector ext, std::string crs); SpatRaster(std::vector fname, std::vector subds, std::vector subdsname, bool multi, std::vector options, std::vector x); SpatRaster(std::string fname, std::vector subds, std::vector subdsname, std::vector options); SpatRaster(SpatRasterSource s); virtual ~SpatRaster(){} void setSource(SpatRasterSource s); void setSources(std::vector s); //SpatRaster(const SpatRaster& x); SpatRaster deepCopy(); SpatRaster hardCopy(SpatOptions &opt); SpatRaster geometry(long nlyrs=-1, bool properties=false, bool time=true, bool units=false); bool constructFromFile(std::string fname, std::vector subds, std::vector subdsname, std::vector options); bool constructFromFileMulti(std::string fname, std::string subdsname, std::vector xyz); bool constructFromSDS(std::string filename, std::vector meta, std::vector subds, std::vector subdsname, std::vector options, bool ncdf); SpatRaster fromFiles(std::vector fname, std::vector subds, std::vector subdsname, std::vector options); // bool constructFromNCDFsds(std::string filename, std::vector meta, std::vector subds, std::vector subdsname); void addSource(SpatRaster x, bool warn, SpatOptions &opt); SpatRaster combineSources(SpatRaster x, bool warn); void combine(SpatRaster x); SpatRaster subset(std::vector lyrs, SpatOptions &opt); SpatRaster replace(SpatRaster x, unsigned layer, SpatOptions &opt); //////////////////////////////////////////////////// // helper methods //////////////////////////////////////////////////// void gdalogrproj_init(std::string path); bool compare_geom(SpatRaster x, bool lyrs, bool crs, double tol, bool warncrs=false, bool ext=true, bool rowcol=true, bool res=false); bool compare_origin(std::vector x, double tol); bool shared_basegeom(SpatRaster &x, double tol, bool test_overlap); std::vector cellFromXY (std::vector x, std::vector y); double cellFromXY(double x, double y); std::vector cellFromRowCol(std::vector row, std::vector col); double cellFromRowCol(int_64 row, int_64 col); std::vector cellFromRowColCombine(std::vector row, std::vector col); double cellFromRowColCombine(int_64 row, int_64 col); std::vector yFromRow(const std::vector &row); double yFromRow(int_64 row); std::vector xFromCol(const std::vector &col); double xFromCol(int_64 col); std::vector colFromX(const std::vector &x); int_64 colFromX(double x); std::vector rowFromY(const std::vector &y); int_64 rowFromY(double y); std::vector> xyFromCell( std::vector &cell); std::vector> xyFromCell( double cell); std::vector> rowColFromCell(std::vector &cell); std::vector rowColFromY(std::vector &y); std::vector> rowColFromExtent(SpatExtent e); std::vector sourcesFromLyrs(std::vector lyrs); int sourceFromLyr(unsigned lyr); std::vector findLyr(unsigned lyr); std::vector getBands(); std::vector nlyrBySource(); std::vector lyrsBySource(); unsigned nsrc(); SpatRaster makeCategorical(unsigned layer, SpatOptions &opt); bool createCategories(unsigned layer, SpatOptions &opt); std::vector hasCategories(); bool setCategories(unsigned layer, SpatDataFrame d, unsigned index); bool removeCategories(unsigned layer); std::vector getCategories(); SpatCategories getLayerCategories(unsigned layer); std::vector getLabels(unsigned layer); bool setLabels(unsigned layer, std::vector value, std::vector labels, std::string name); int getCatIndex(unsigned layer); bool setCatIndex(unsigned layer, unsigned index); //bool setAttrIndex(size_t layer, int i); //std::vector getAttrIndex(); //void createAttributes(unsigned layer); //std::vector hasAttributes(); //void setAttributes(unsigned layer, SpatDataFrame df); //std::vector getAttributes(); //SpatDataFrame getLayerAttributes(unsigned layer); std::vector hasColors(); std::vector getColors(); bool setColors(size_t layer, SpatDataFrame cols); bool removeColors(size_t layer); double valuesCell(double); double valuesCell(int, int); std::vector valuesCell(std::vector); std::vector valuesRow(int); //////////////////////////////////////////////////// // read and write //////////////////////////////////////////////////// bool valid_sources(bool files=true, bool rotated=true); bool readStart(); std::vector readValuesR(size_t row, size_t nrows, size_t col, size_t ncols); void readValues(std::vector &out, size_t row, size_t nrows, size_t col, size_t ncols); void readChunkMEM(std::vector &out, size_t src, size_t row, size_t nrows, size_t col, size_t ncols); void readBlock(std::vector &v, BlockSize bs, unsigned i){ // inline readValues(v, bs.row[i], bs.nrows[i], 0, ncol()); } void readBlock2(std::vector> &v, BlockSize bs, unsigned i); std::vector readBlockIP(BlockSize bs, unsigned i); std::vector readExtent(SpatExtent e); bool readStop(); bool readAll(); bool writeStart(SpatOptions &opt); bool writeBlock(std::vector &v, unsigned i){ // inline // for debugging? // if (bs.row.size() <= i) { // setError("invalid block number"); return false; // } return writeValues(v, bs.row[i], bs.nrows[i]); } bool writeValues(std::vector &vals, size_t startrow, size_t nrows); bool writeValuesRect(std::vector &vals, size_t startrow, size_t nrows, size_t startcol, size_t ncols); //bool writeValues2(std::vector> &vals, size_t startrow, size_t nrows); bool writeStop(); bool writeHDR(std::string filename); SpatRaster make_vrt(std::vector filenames, SpatOptions &opt); bool write_aux_json(std::string filename); //bool writeStartGDAL(std::string filename, std::string driver, std::string datatype, bool overwrite, SpatOptions &opt); bool writeStartGDAL(SpatOptions &opt); bool fillValuesGDAL(double fillvalue); bool writeValuesGDAL(std::vector &vals, size_t startrow, size_t nrows, size_t startcol, size_t ncols); bool writeStopGDAL(); bool readStartMulti(unsigned src); bool readStopMulti(unsigned src); bool readValuesMulti(std::vector &data, size_t src, size_t row, size_t nrows, size_t col, size_t ncols); //bool writeStartBinary(std::string filename, std::string datatype, std::string bandorder, bool overwrite); //bool writeValuesBinary(std::vector &vals, unsigned startrow, unsigned nrows, unsigned startcol, unsigned ncols); bool writeValuesMem(std::vector &vals, size_t startrow, size_t nrows); bool writeValuesMemRect(std::vector &vals, size_t startrow, size_t nrows, size_t startcol, size_t ncols); // binary (flat) source //std::vector readValuesBinary(unsigned src, unsigned row, unsigned nrows, unsigned col, unsigned ncols); //std::vector readSampleBinary(unsigned src, unsigned srows, unsigned scols); //std::vector> readCellsBinary(unsigned src, std::vector cells); // gdal source std::vector readValuesGDAL(unsigned src, size_t row, size_t nrows, size_t col, size_t ncols, int lyr = -1); std::vector readGDALsample(unsigned src, size_t srows, size_t scols); std::vector> readRowColGDAL(unsigned src, std::vector &rows, const std::vector &cols); std::vector readRowColGDALFlat(unsigned src, std::vector &rows, const std::vector &cols); bool readStartGDAL(unsigned src); bool readStopGDAL(unsigned src); void readChunkGDAL(std::vector &data, unsigned src, size_t row, unsigned nrows, size_t col, unsigned ncols); bool setWindow(SpatExtent x); bool removeWindow(); std::vector hasWindow(); void openFS(std::string const &filename); SpatRaster writeRaster(SpatOptions &opt); //SpatRaster writeRasterGDAL(std::string filename, std::string format, std::string datatype, bool overwrite, SpatOptions &opt); //SpatRaster writeRasterBinary(std::string filename, std::string datatype, std::string bandorder, bool overwrite); //bool checkFormatRequirements(const std::string &driver, std::string &filename); bool canProcessInMemory(SpatOptions &opt); size_t chunkSize(SpatOptions &opt); void fill(double x); SpatRaster sources_to_disk(std::vector &tmpfs, bool unique, SpatOptions &opt); bool sources_from_file(); bool differentFilenames(std::vector outf, bool &duplicates, bool &empty); std::vector getFileBlocksize(); //////////////////////////////////////////////////// // main methods //////////////////////////////////////////////////// SpatRaster collapse_sources(); void collapse(); SpatRaster rectify(std::string method, SpatRaster aoi, unsigned useaoi, bool snap, SpatOptions &opt); std::vector adjacent(std::vector cells, std::string directions, bool include); std::vector adjacentMat(std::vector cells, std::vector mat, std::vector dim, bool include); SpatRaster aggregate(std::vector fact, std::string fun, bool narm, SpatOptions &opt); SpatExtent align(SpatExtent e, std::string snap); SpatRaster rst_area(bool mask, std::string unit, bool transform, SpatOptions &opt); std::vector sum_area(std::string unit, bool transform, SpatOptions &opt); std::vector> area_by_value(SpatOptions &opt); SpatRaster arith(SpatRaster x, std::string oper, SpatOptions &opt); SpatRaster arith(double x, std::string oper, bool reverse, SpatOptions &opt); SpatRaster arith(std::vector x, std::string oper, bool reverse, SpatOptions &opt); SpatRaster apply(std::vector ind, std::string fun, bool narm, std::vector nms, SpatOptions &opt); SpatRaster rapply(SpatRaster x, double first, double last, std::string fun, bool clamp, bool narm, SpatOptions &opt); std::vector> rappvals(SpatRaster x, double first, double last, bool clamp, bool all, double fill, size_t startrow, size_t nrows); SpatVector as_polygons(bool trunc, bool dissolve, bool values, bool narm, SpatOptions &opt); SpatVector polygonize(bool trunc, bool values, bool narm, bool aggregate, SpatOptions &opt); SpatVector as_lines(SpatOptions &opt); SpatVector as_points(bool values, bool narm, SpatOptions &opt); SpatRaster atan_2(SpatRaster x, SpatOptions &opt); std::vector> bilinearValues(const std::vector &x, const std::vector &y); std::vector bilinearCells(const std::vector &x, const std::vector &y); std::vector fourCellsFromXY(const std::vector &x, const std::vector &y); SpatRaster buffer(double d, SpatOptions &opt); SpatRaster clamp(double low, double high, bool usevalue, SpatOptions &opt); SpatRaster cover(SpatRaster x, std::vector value, SpatOptions &opt); SpatRaster crop(SpatExtent e, std::string snap, SpatOptions &opt); SpatRaster cropmask(SpatVector v, std::string snap, SpatOptions &opt); SpatRaster cum(std::string fun, bool narm, SpatOptions &opt); SpatRaster disaggregate(std::vector fact, SpatOptions &opt); SpatRaster distance(SpatOptions &opt); SpatRaster disdir_vector_rasterize(SpatVector p, bool align_points, bool distance, bool from, bool degrees, SpatOptions &opt); SpatRaster distance_vector(SpatVector p, SpatOptions &opt); SpatRaster direction(bool from, bool degrees, SpatOptions &opt); SpatRaster direction_vector(SpatVector p, bool from, bool degrees, SpatOptions &opt); SpatRaster clumps(int directions, bool zeroAsNA, SpatOptions &opt); SpatRaster edges(bool classes, std::string type, unsigned directions, double falseval, SpatOptions &opt); SpatRaster extend(SpatExtent e, std::string snap, SpatOptions &opt); std::vector>> extractVector(SpatVector v, bool touches, std::string method, bool cells, bool xy, bool weights, bool exact, SpatOptions &opt); std::vector extractVectorFlat(SpatVector v, bool touches, std::string method, bool cells, bool xy, bool weights, bool exact, SpatOptions &opt); std::vector vectCells(SpatVector v, bool touches, std::string method, bool weights, bool exact, SpatOptions &opt); std::vector extCells(SpatExtent ext); std::vector> extractCell(std::vector &cell); std::vector extractCellFlat(std::vector &cell); std::vector> extractXY(const std::vector &x, const std::vector &y, const std::string & method, const bool &cells); std::vector extractXYFlat(const std::vector &x, const std::vector &y, const std::string & method, const bool &cells); SpatRaster flip(bool vertical, SpatOptions &opt); SpatRaster filler(SpatRaster x, SpatOptions &opt); SpatRaster focal(std::vector w, std::vector m, double fillvalue, bool narm, bool naonly, bool naomit, std::string fun, bool expand, SpatOptions &opt); std::vector focal_values(std::vector w, double fillvalue, int_64 row, int_64 nrows, SpatOptions &opt); std::vector> freq(bool bylayer, bool round, int digits, SpatOptions &opt); std::vector count(double value, bool bylayer, bool round, int digits, SpatOptions &opt); bool get_aggregate_dims(std::vector &fact, std::string &message); std::vector get_aggregate_dims2(std::vector fact); std::vector > get_aggregates(std::vector &in, size_t nr, std::vector dim); // std::vector compute_aggregates(std::vector &in, size_t nr, std::vector dim, std::function&, bool)> fun, bool narm); SpatDataFrame global(std::string fun, bool narm, SpatOptions &opt); SpatDataFrame global_weighted_mean(SpatRaster &weights, std::string fun, bool narm, SpatOptions &opt); SpatRaster gridDistance(SpatOptions &opt); SpatRaster costDistance(double source, SpatOptions &opt); SpatRaster init(std::string value, bool plusone, SpatOptions &opt); SpatRaster init(std::vector values, SpatOptions &opt); SpatRaster is_in(std::vector m, SpatOptions &opt); std::vector> is_in_cells(std::vector m, SpatOptions &opt); SpatRaster isnot(SpatOptions &opt); SpatRaster isnan(SpatOptions &opt); SpatRaster isnotnan(SpatOptions &opt); SpatRaster isfinite(SpatOptions &opt); SpatRaster isinfinite(SpatOptions &opt); std::vector line_cells(SpatGeom& g); SpatRaster logic(SpatRaster x, std::string oper, SpatOptions &opt); SpatRaster logic(bool x, std::string oper, SpatOptions &opt); SpatExtent ext_from_rc(int_64 r1, int_64 r2, int_64 c1, int_64 c2); SpatExtent ext_from_cell(double cell); std::vector make_tiles(SpatRaster x, bool expand, bool narm, std::string filename, SpatOptions &opt); SpatRaster mask(SpatRaster x, bool inverse, double maskvalue, double updatevalue, SpatOptions &opt); SpatRaster mask(SpatRaster x, bool inverse, std::vector maskvalues, double updatevalue, SpatOptions &opt); SpatRaster mask(SpatVector x, bool inverse, double updatevalue, bool touches, SpatOptions &opt); SpatRaster math(std::string fun, SpatOptions &opt); SpatRaster math2(std::string fun, unsigned digits, SpatOptions &opt); SpatRaster separate(std::vector classes, double keepvalue, double othervalue, SpatOptions &opt); SpatRaster modal(std::vector add, std::string ties, bool narm, SpatOptions &opt); std::vector polygon_cells(SpatGeom& g); SpatRaster quantile(std::vector probs, bool narm, SpatOptions &opt); SpatRaster stretch(std::vector minv, std::vector maxv, std::vector minq, std::vector maxq, std::vector smin, std::vector smax, SpatOptions &opt); SpatRaster reverse(SpatOptions &opt); SpatRaster range(std::vector add, bool narm, SpatOptions &opt); SpatRaster rasterizeLyr(SpatVector x, double value, double background, bool touches, bool update, SpatOptions &opt); SpatRaster rasterize(SpatVector x, std::string field, std::vector values, double background, bool touches, bool add, bool weights, bool update, bool minmax, SpatOptions &opt); std::vector rasterizeCells(SpatVector &v, bool touches, SpatOptions &opt); //std::vector> rasterizeCellsWeights(SpatVector &v, bool touches); void rasterizeCellsWeights(std::vector &cells, std::vector &weights, SpatVector &v, SpatOptions &opt); void rasterizeCellsExact(std::vector &cells, std::vector &weights, SpatVector &v, SpatOptions &opt); SpatRaster replaceValues(std::vector from, std::vector to, long nl, SpatOptions &opt); SpatRaster reclassify(std::vector> rcl, unsigned openclosed, bool lowest, bool othersNA, bool bylayer, bool brackets, SpatOptions &opt); SpatRaster reclassify(std::vector rcl, unsigned nc, unsigned openclosed, bool lowest, bool othersNA, bool bylayer, bool brackets, SpatOptions &opt); //SpatRaster classify_layers(std::vector> groups, std::vector id, SpatOptions &opt); //SpatRaster classify_layers(std::vector groups, unsigned nc, std::vector id, SpatOptions &opt); std::vector readSample(unsigned src, size_t srows, size_t scols); SpatRaster rotate(bool left, SpatOptions &opt); std::vector sampleCells(unsigned size, std::string method, bool replace, unsigned seed); SpatRaster sampleRegularRaster(unsigned size); SpatRaster sampleRowColRaster(size_t nr, size_t nc); SpatRaster sampleRandomRaster(unsigned size, bool replace, unsigned seed); std::vector> sampleRegularValues(unsigned size, SpatOptions &opt); std::vector> sampleRowColValues(size_t nr, size_t nc, SpatOptions &opt); std::vector> sampleRandomValues(unsigned size, bool replace, unsigned seed); SpatRaster scale(std::vector center, bool docenter, std::vector scale, bool doscale, SpatOptions &opt); SpatRaster terrain(std::vector v, unsigned neighbors, bool degrees, unsigned seed, SpatOptions &opt); SpatRaster selRange(SpatRaster x, int z, int recycleby, SpatOptions &opt); SpatRaster selectHighest(size_t n, bool low, SpatOptions &opt); SpatRaster shift(double x, double y, SpatOptions &opt); SpatRaster summary(std::string fun, bool narm, SpatOptions &opt); SpatRaster summary_numb(std::string fun, std::vector add, bool narm, SpatOptions &opt); SpatRaster transpose(SpatOptions &opt); SpatRaster trig(std::string fun, SpatOptions &opt); SpatRaster trim(double value, unsigned padding, SpatOptions &opt); std::vector> unique(bool bylayer, SpatOptions &opt); SpatRaster project1(std::string newcrs, std::string method, SpatOptions &opt); SpatRaster project2(SpatRaster &x, std::string method, SpatOptions &opt); void project3(SpatRaster &out, std::string method, SpatOptions &opt); #ifdef useGDAL bool getDSh(GDALDatasetH &rstDS, SpatRaster &out, std::string &filename, std::string &driver, double &naval, bool update, double background, SpatOptions &opt); bool open_gdal(GDALDatasetH &hDS, int src, bool update, SpatOptions &opt); bool create_gdalDS(GDALDatasetH &hDS, std::string filename, std::string driver, bool fill, double fillvalue, std::vector has_so, std::vector scale, std::vector offset, SpatOptions& opt); bool from_gdalMEM(GDALDatasetH hDS, bool set_geometry, bool get_values); bool as_gdalvrt(GDALDatasetH &hVRT, SpatOptions &opt); //bool as_gdalmem(GDALDatasetH &hVRT); #endif SpatRaster to_memory_copy(SpatOptions &opt); bool to_memory(SpatOptions &opt); SpatRaster weighted_mean(SpatRaster w, bool narm, SpatOptions &opt); SpatRaster weighted_mean(std::vector w, bool narm, SpatOptions &opt); SpatRaster warper(SpatRaster x, std::string crs, std::string method, bool mask, bool align, SpatOptions &opt); SpatRaster resample(SpatRaster x, std::string method, bool mask, bool agg, SpatOptions &opt); SpatRaster applyGCP(std::vector fx, std::vector fy, std::vector tx, std::vector ty, SpatOptions &opt); SpatDataFrame zonal(SpatRaster x, std::string fun, bool narm, SpatOptions &opt); SpatRaster rgb2col(size_t r, size_t g, size_t b, SpatOptions &opt); SpatRaster rgb2hsx(std::string type, SpatOptions &opt); SpatRaster hsx2rgb(SpatOptions &opt); SpatRaster which(SpatOptions &opt); SpatRaster is_true(SpatOptions &opt); SpatRaster is_false(SpatOptions &opt); SpatRaster sieveFilter(int threshold, int connections, SpatOptions &opt); // SpatRaster panSharpen(SpatRaster pan, SpatOptions &opt); }; terra/src/spatVector.h0000644000175000017500000002666314201626135014630 0ustar nileshnilesh// Copyright (c) 2018-2020 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . //#include "spatBase.h" #include "spatDataframe.h" //#include "spatMessages.h" #ifdef useGDAL #include "gdal_priv.h" #endif enum SpatGeomType { points, lines, polygons, unknown }; class SpatHole { public: virtual ~SpatHole(){} std::vector x, y; SpatExtent extent; //constructors SpatHole(); SpatHole(std::vector X, std::vector Y); //methods size_t size() { return x.size(); } }; class SpatPart { public: virtual ~SpatPart(){} std::vector x, y; //, z; std::vector< SpatHole > holes; // polygons only SpatExtent extent; //constructors SpatPart(); SpatPart(std::vector X, std::vector Y); SpatPart(double X, double Y); //methods size_t size() { return x.size(); } //holes, polygons only bool addHole(std::vector X, std::vector Y); bool addHole(SpatHole h); SpatHole getHole(unsigned i) { return( holes[i] ) ; } bool hasHoles() { return holes.size() > 0;} unsigned nHoles() { return holes.size();} }; class SpatGeom { public: //constructors SpatGeom(); SpatGeom(SpatGeomType g); SpatGeom(SpatPart p); virtual ~SpatGeom(){} SpatGeomType gtype = unknown; std::vector parts; SpatExtent extent; //methods bool unite(SpatGeom g); bool addPart(SpatPart p); bool addHole(SpatHole h); bool setPart(SpatPart p, unsigned i); bool reSetPart(SpatPart p); SpatPart getPart(unsigned i); //double area_plane(); //double area_lonlat(double a, double f); //double length_plane(); //double length_lonlat(double a, double f); unsigned size() { return parts.size(); }; void remove_duplicate_nodes(int digits); size_t ncoords(); std::vector> coordinates(); }; class SpatVectorCollection; class SpatVector { public: std::vector geoms; SpatExtent extent; SpatDataFrame df; //std::vector crs; SpatSRS srs; bool is_proxy = false; std::string read_query = ""; std::vector read_extent; std::string source = ""; std::string source_layer = ""; size_t geom_count = 0; SpatVector(); //SpatVector(const SpatVector &x); SpatVector(SpatGeom g); SpatVector(SpatExtent e, std::string crs); SpatVector(std::vector x, std::vector y, SpatGeomType g, std::string crs); SpatVector(std::vector wkt); virtual ~SpatVector(){} SpatGeom window; // for point patterns, must be polygon std::vector get_names(); void set_names(std::vector s); unsigned nrow(); unsigned ncol(); unsigned nxy(); SpatVector deepCopy() {return *this;} void reserve(size_t n) { geoms.reserve(n); } SpatExtent getExtent(); // bool is_geographic(); bool is_lonlat(); bool could_be_lonlat(); std::string type(); SpatGeomType getGType(std::string &type); //std::vector getCRS(); //void setCRS(std::vector _crs); bool setSRS(std::string _srs) { std::string msg; if (!srs.set(_srs, msg)){ addWarning("Cannot set SRS to vector: "+ msg); return false; } return true; } std::string getSRS(std::string x) { return srs.get(x); } SpatGeom getGeom(unsigned i); bool addGeom(SpatGeom p); bool setGeom(SpatGeom p); bool replaceGeom(SpatGeom p, unsigned i); std::vector> getGeometry(); SpatDataFrame getGeometryDF(); std::vector getGeometryWKT(); void computeExtent(); size_t ncoords(); std::vector> coordinates(); SpatVector project(std::string crs); SpatVector subset_cols(int i); SpatVector subset_cols(std::vector range); SpatVector subset_rows(int i); SpatVector subset_rows(std::vector range); SpatVector subset_rows(std::vector range); SpatVector remove_rows(std::vector range); void setGeometry(std::string type, std::vector gid, std::vector part, std::vector x, std::vector y, std::vector hole); void setPointsGeometry(std::vector &x, std::vector &y); void setPointsDF(SpatDataFrame &x, std::vector geo, std::string crs); std::vector area(std::string unit, bool transform, std::vector mask); std::vector length(); std::vector distance(SpatVector x, bool pairwise); std::vector distance(bool sequential); std::vector linedistLonLat(SpatVector pts); std::vector> knearest(size_t k); size_t size(); SpatVector as_lines(); SpatVector as_points(bool multi, bool skiplast=false); SpatVector remove_holes(); SpatVector get_holes(); SpatVector set_holes(SpatVector x, size_t i); SpatVector remove_duplicate_nodes(int digits); bool read(std::string fname, std::string layer, std::string query, std::vector extent, SpatVector filter, bool as_proxy); bool write(std::string filename, std::string lyrname, std::string driver, bool append, bool overwrite, std::vector); #ifdef useGDAL GDALDataset* write_ogr(std::string filename, std::string lyrname, std::string driver, bool append, bool overwrite, std::vector options); GDALDataset* GDAL_ds(); bool read_ogr(GDALDataset *poDS, std::string layer, std::string query, std::vector extent, SpatVector filter, bool as_proxy); SpatVector fromDS(GDALDataset *poDS); bool ogr_geoms(std::vector &ogrgeoms, std::string &message); bool delete_layers(std::string filename, std::vector layers, bool return_error); std::vector layer_names(std::string filename); #endif // attributes std::vector getDv(unsigned i); std::vector getIv(unsigned i); std::vector getSv(unsigned i); std::vector getItype(); std::vector getIplace(); void add_column(unsigned dtype, std::string name) { df.add_column(dtype, name); }; template bool add_column(std::vector x, std::string name) { return df.add_column(x, name); } void remove_df() { SpatDataFrame empty; df = empty; }; bool remove_column(std::string field) { return df.remove_column(field); }; bool remove_column(int i) { return df.remove_column(i); }; std::vector get_datatypes() { return df.get_datatypes(); } SpatMessages msg; void setError(std::string s) { msg.setError(s); } void addWarning(std::string s) { msg.addWarning(s); } bool hasError() { return msg.has_error; } bool hasWarning() { return msg.has_warning; } std::string getWarnings() { return msg.getWarnings();} std::string getError() { return msg.getError();} SpatVector append(SpatVector x, bool ignorecrs); SpatVector disaggregate(); SpatVector shift(double x, double y); SpatVector rescale(double fx, double fy, double x0, double y0); SpatVector transpose(); SpatVector flip(bool vertical); SpatVector rotate(double angle, double x0, double y0); //ogr std::vector is_valid(); SpatVector make_valid(); //geos SpatVector make_valid2(); std::vector geos_isvalid(); std::vector geos_isvalid_msg(); std::vector wkt(); std::vector wkb(); std::vector hex(); SpatVector from_hex(std::vector x, std::string srs); SpatVector make_nodes(); SpatVector polygonize(); SpatVector normalize(); SpatVector boundary(); SpatVector line_merge(); SpatVector simplify(double tolerance, bool preserveTopology); SpatVector shared_paths(); SpatVector snap(double tolerance); SpatVector snapto(SpatVector y, double tolerance); SpatVector allerretour(); SpatVectorCollection bienvenue(); SpatVector aggregate(bool dissolve); SpatVector aggregate(std::string field, bool dissolve); SpatVector buffer(std::vector d, unsigned quadsegs); SpatVector point_buffer(std::vector d, unsigned quadsegs, bool no_multipolygons); SpatVector centroid(bool check_lonlat); SpatVector crop(SpatExtent e); SpatVector crop(SpatVector e); SpatVector voronoi(SpatVector e, double tolerance, int onlyEdges); SpatVector delauny(double tolerance, int onlyEdges); SpatVector hull(std::string htype, std::string by=""); SpatVector intersect(SpatVector v); SpatVector unite(SpatVector v); SpatVector unite(); SpatVector erase_agg(SpatVector v); SpatVector erase(SpatVector v); SpatVector erase(); SpatVector mask(SpatVector x, bool inverse); SpatVector gaps(); SpatVector cover(SpatVector v, bool identity); SpatVectorCollection split(std::string field); SpatVector symdif(SpatVector v); std::vector is_related(SpatVector v, std::string relation); std::vector relate(SpatVector v, std::string relation); std::vector relate(std::string relation, bool symmetrical); std::vector relateFirst(SpatVector v, std::string relation); std::vector geos_distance(SpatVector v, bool parallel); std::vector geos_distance(bool sequential); SpatVector nearest_point(SpatVector v, bool parallel); SpatVector nearest_point(); SpatVector sample(unsigned n, std::string method, unsigned seed); SpatVector sample_geom(std::vector n, std::string method, unsigned seed); SpatVector clearance(); SpatVector width(); SpatVector unaryunion(); SpatVector cbind(SpatDataFrame d); void fix_lonlat_overflow(); SpatVector cross_dateline(bool &fixed); SpatVector densify(double interval, bool adjust); SpatVector round(int digits); }; class SpatVectorCollection { private: std::vector v; public: virtual ~SpatVectorCollection(){} SpatVectorCollection deepCopy() { return *this; } SpatMessages msg; void setError(std::string s) { msg.setError(s); } void addWarning(std::string s) { msg.addWarning(s); } bool hasError() { return msg.has_error; } bool hasWarning() { return msg.has_warning; } std::string getWarnings() { return msg.getWarnings();} std::string getError() { return msg.getError();} size_t size() { return v.size(); } void push_back(SpatVector x) { v.push_back(x); }; bool replace(SpatVector x, size_t i) { if (i < size()) { v[i] = x; return true; } else { return false; } } SpatVectorCollection subset(std::vector i) { SpatVectorCollection out; for (size_t j=0; j extent, SpatVector filter); }; terra/src/distance.cpp0000644000175000017500000003222514201035750014607 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #ifndef M_PI #define M_PI (3.14159265358979323846) #endif #include //#include #include #include "geodesic.h" #include "recycle.h" double distance_lonlat(const double &lon1, const double &lat1, const double &lon2, const double &lat2) { double a = 6378137.0; double f = 1/298.257223563; double s12, azi1, azi2; struct geod_geodesic g; geod_init(&g, a, f); geod_inverse(&g, lat1, lon1, lat2, lon2, &s12, &azi1, &azi2); return s12; } std::vector distance_lonlat(std::vector &lon1, std::vector &lat1, std::vector &lon2, std::vector &lat2) { double a = 6378137.0; double f = 1/298.257223563; recycle(lon1, lon2); recycle(lat1, lat2); std::vector r (lon1.size()); double azi1, azi2; struct geod_geodesic g; geod_init(&g, a, f); size_t n = lat1.size(); for (size_t i=0; i < n; i++) { geod_inverse(&g, lat1[i], lon1[i], lat2[i], lon2[i], &r[i], &azi1, &azi2); } return r; } std::vector distance_lonlat_vd(std::vector &lon1, std::vector &lat1, double lon2, double lat2) { std::vector vlon2(lon1.size(), lon2); std::vector vlat2(lat1.size(), lat2); return distance_lonlat(lon1, lat1, vlon2, vlat2); } double distance_plane(const double &x1, const double &y1, const double &x2, const double &y2) { return( sqrt(pow((x2-x1),2) + pow((y2-y1), 2)) ); } std::vector distance_plane(std::vector &x1, std::vector &y1, std::vector &x2, std::vector &y2) { recycle(x1, x2); recycle(y1, y2); std::vector r (x1.size()); size_t n = x1.size(); for (size_t i=0; i < n; i++) { r[i] = distance_plane(x1[i], y1[i], x2[i], y2[i]); } return r; } std::vector distance_plane_vd(std::vector &x1, std::vector &y1, double x2, double y2) { std::vector vx2(x1.size(), x2); std::vector vy2(y1.size(), y2); return distance_plane(x1, y1, vx2, vy2); } /* double distPlane(double x1, double y1, double x2, double y2) { return( sqrt(pow((x2-x1),2) + pow((y2-y1), 2)) ); } */ // Convert degrees to radians double toRad(double °) { return( deg * 0.0174532925199433 ); } double toDeg(double &rad) { return( rad * 57.2957795130823 ); } double direction_lonlat(double lon1, double lat1, double lon2, double lat2, bool degrees) { double a = 6378137.0; double f = 1/298.257223563; double s12, azi1, azi2; struct geod_geodesic g; geod_init(&g, a, f); geod_inverse(&g, lat1, lon1, lat2, lon2, &s12, &azi1, &azi2); if (!degrees) { return(toRad(azi1)); } return( azi1) ; } std::vector direction_lonlat(std::vector lon1, std::vector lat1, std::vector lon2, std::vector lat2, bool degrees) { double a = 6378137.0; double f = 1/298.257223563; // lonlat1 and lonlat2 should have the same length std::vector azi1(lon1.size()); double s12, azi2; struct geod_geodesic g; geod_init(&g, a, f); size_t n = lat1.size(); if (degrees) { for (size_t i=0; i < n; i++) { geod_inverse(&g, lat1[i], lon1[i], lat2[i], lon2[i], &s12, &azi1[i], &azi2); } } else { for (size_t i=0; i < n; i++) { geod_inverse(&g, lat1[i], lon1[i], lat2[i], lon2[i], &s12, &azi1[i], &azi2); azi1[i] = toRad(azi1[i]); } } return azi1; } void directionToNearest_lonlat(std::vector &azi, const std::vector &lon1, const std::vector &lat1, const std::vector &lon2, const std::vector &lat2, bool& degrees, bool& from) { double a = 6378137.0; double f = 1/298.257223563; double azi1, azi2, s12, dist; size_t n = lon1.size(); size_t m = lon2.size(); azi.resize(n, NAN); struct geod_geodesic g; geod_init(&g, a, f); for (size_t i=0; i < n; i++) { if (std::isnan(lat1[i])) { azi[i] = NAN; continue; } geod_inverse(&g, lat1[i], lon1[i], lat2[0], lon2[0], &dist, &azi1, &azi2); size_t minj=0; azi[i] = azi1; for (size_t j=1; j direction_plane(std::vector x1, std::vector y1, std::vector x2, std::vector y2, bool degrees) { // xy1 and xy2 should have the same length std::vector r (x1.size()); //double a; size_t n = x1.size(); for (size_t i=0; i < n; i++) { r[i] = direction_plane(x1[i], y1[i], x2[i], y2[i], degrees); } return r; } void directionToNearest_plane(std::vector &r, const std::vector &x1, const std::vector &y1, const std::vector &x2, const std::vector &y2, bool& degrees, bool &from) { size_t n = x1.size(); size_t m = x2.size(); r.resize(n, NAN); double d, mind; size_t minj; for (size_t i = 0; i < n; i++) { r[i] = NAN; if (std::isnan(x1[i])) continue; // x2 must not be NAN mind = distance_plane(x1[i], y1[i], x2[0], y2[0]); minj = 0; for (size_t j = 1; j < m; j++) { d = distance_plane(x1[i], y1[i], x2[j], y2[j]); if (d < mind) { mind = d; minj = j; } } if (from) { r[i] = direction_plane(x2[minj], y2[minj], x1[i], y1[i], degrees); } else { r[i] = direction_plane(x1[i], y1[i], x2[minj], y2[minj], degrees); } } } std::vector destpoint_lonlat(double longitude, double latitude, double bearing, double distance) { double a = 6378137.0; double f = 1/298.257223563; struct geod_geodesic g; geod_init(&g, a, f); double lat2, lon2, azi2; geod_direct(&g, latitude, longitude, bearing, distance, &lat2, &lon2, &azi2); std::vector out = { lon2, lat2, azi2 }; return out; } std::vector > destpoint_lonlat(const std::vector &longitude, const std::vector &latitude, const std::vector &bearing, const std::vector &distance) { double a = 6378137.0; double f = 1/298.257223563; struct geod_geodesic g; geod_init(&g, a, f); size_t n = longitude.size(); std::vector > out(3, std::vector(n)); double lat2, lon2, azi2; for (size_t i=0; i < n; i++) { geod_direct(&g, latitude[i], longitude[i], bearing[i], distance[i], &lat2, &lon2, &azi2); out[0][i] = lon2; out[1][i] = lat2; out[2][i] = azi2; } return out; } std::vector > destpoint_lonlat(const double &longitude, const double &latitude, const std::vector &bearing, const double& distance, bool wrap) { double a = 6378137.0; double f = 1/298.257223563; struct geod_geodesic g; geod_init(&g, a, f); size_t n = bearing.size(); std::vector > out(3, std::vector(n)); double lat2, lon2, azi2; if (wrap) { for (size_t i=0; i < n; i++) { geod_direct(&g, latitude, longitude, bearing[i], distance, &lat2, &lon2, &azi2); out[0][i] = lon2; out[1][i] = lat2; out[2][i] = azi2; } } else { for (size_t i=0; i < n; i++) { geod_direct(&g, latitude, 0, bearing[i], distance, &lat2, &lon2, &azi2); out[0][i] = lon2 + longitude; out[1][i] = lat2; out[2][i] = azi2; } } return out; } std::vector destpoint_plane(double x, double y, double bearing, double distance) { bearing = bearing * M_PI / 180; x += distance * sin(bearing); y += distance * cos(bearing); std::vector out = {x, y}; return(out); } std::vector > destpoint_plane(std::vector x, std::vector y, std::vector bearing, std::vector distance) { size_t n = x.size(); std::vector > out; out.reserve(n); double xd, yd, b; for (size_t i=0; i < n; i++) { b = bearing[i] * M_PI / 180; xd = x[i] + distance[i] * sin(b); yd = y[i] + distance[i] * cos(b); out.push_back( {xd, yd }); } return(out); } void distanceToNearest_lonlat(std::vector &d, const std::vector &lon1, const std::vector &lat1, const std::vector &lon2, const std::vector &lat2) { int n = lon1.size(); int m = lon2.size(); double a = 6378137.0; double f = 1/298.257223563; double azi1, azi2, s12; struct geod_geodesic g; geod_init(&g, a, f); for (int i=0; i < n; i++) { if (std::isnan(lat1[i])) { continue; } geod_inverse(&g, lat1[i], lon1[i], lat2[0], lon2[0], &d[i], &azi1, &azi2); for (int j=1; j &d, const std::vector &lon1, const std::vector &lat1, const std::vector &lon2, const std::vector &lat2) { int n = lon1.size(); int m = lon2.size(); double s12; for (int i=0; i < n; i++) { if (std::isnan(lat1[i])) { continue; } d[i] = distCosine(lat1[i], lon1[i], lat2[0], lon2[0]); for (int j=1; j &d, const std::vector &x1, const std::vector &y1, const std::vector &x2, const std::vector &y2, const double& lindist) { int n = x1.size(); int m = x2.size(); for (int i=0; i < n; i++) { if (std::isnan(x1[i])) continue; d[i] = sqrt(pow((x2[0]-x1[i]),2) + pow((y2[0]-y1[i]), 2)) * lindist; for (int j=1; j < m; j++) { double r = sqrt(pow((x2[j]-x1[i]),2) + pow((y2[j]-y1[i]), 2)); if (r < d[i]) { d[i] = r * lindist; } } } } void nearest_lonlat(std::vector &id, std::vector &d, std::vector &nlon, std::vector &nlat, const std::vector &lon1, const std::vector &lat1, const std::vector &lon2, const std::vector &lat2) { size_t n = lon1.size(); size_t m = lon2.size(); double a = 6378137.0; double f = 1/298.257223563; double azi1, azi2, s12; struct geod_geodesic g; geod_init(&g, a, f); nlon.resize(n); nlat.resize(n); id.resize(n); d.resize(n); for (size_t i=0; i < n; i++) { if (std::isnan(lat1[i])) { nlon[i] = NAN; nlat[i] = NAN; id[i] = -1; d[i] = NAN; continue; } geod_inverse(&g, lat1[i], lon1[i], lat2[0], lon2[0], &d[i], &azi1, &azi2); nlon[i] = lon2[0]; nlat[i] = lat2[0]; id[i] = 0; for (size_t j=1; j &id, std::vector &d, std::vector &nlon, std::vector &nlat, const std::vector &lon, const std::vector &lat) { size_t n = lon.size(); if (n <= 1) { nlon = lon; nlat = lat; if (nlon.size() == 1) { id.resize(1); id[0] = 0; } return; } double a = 6378137.0; double f = 1/298.257223563; double azi1, azi2, s12; struct geod_geodesic g; geod_init(&g, a, f); nlon.resize(n); nlat.resize(n); id.resize(n); d.resize(n); for (size_t i=0; i < n; i++) { if (std::isnan(lat[i])) { id[i] = -1; d[i] = NAN; nlon[i] = NAN; nlat[i] = NAN; continue; } if (i>0) { geod_inverse(&g, lat[i], lon[i], lat[0], lon[0], &d[i], &azi1, &azi2); nlon[i] = lon[0]; nlat[i] = lat[0]; id[i] = 0; } else { geod_inverse(&g, lat[1], lon[1], lat[0], lon[0], &d[i], &azi1, &azi2); nlon[i] = lon[1]; nlat[i] = lat[1]; id[i] = 1; } for (size_t j=1; j < n; j++) { if (j == i) continue; geod_inverse(&g, lat[i], lon[i], lat[j], lon[j], &s12, &azi1, &azi2); if (s12 < d[i]) { d[i] = s12; id[i] = j; nlon[i] = lon[j]; nlat[i] = lat[j]; } } } } double distHaversine(double lon1, double lat1, double lon2, double lat2) { double r = 6378137; double dLat, dLon, a; lon1 = toRad(lon1); lon2 = toRad(lon2); lat1 = toRad(lat1); lat2 = toRad(lat2); dLat = lat2-lat1; dLon = lon2-lon1; a = sin(dLat/2.) * sin(dLat/2.) + cos(lat1) * cos(lat2) * sin(dLon/2.) * sin(dLon/2.); return 2. * atan2(sqrt(a), sqrt(1.-a)) * r; } terra/src/math_utils.h0000644000175000017500000000455614201035750014641 0ustar nileshnilesh// Copyright (c) 2018-2020 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include #include #include #include double modal_value(std::vector values, unsigned ties, bool narm, std::default_random_engine rgen, std::uniform_real_distribution dist); void na_omit(std::vector &x); bool is_equal(double a, double b, double tolerance=10.0); bool about_equal(double a, double b, double tolerance); bool is_equal_relative(double a, double b, double tolerance); bool is_equal_range(double x, double y, double range, double tolerance); void vector_minmax(std::vector v, double &min, int &imin, double &max, int &imax); double roundn(double x, int n); double signif(double x, unsigned n); template void minmaxlim(Iterator start, Iterator end, double &vmin, double &vmax, const double &lmin, const double &lmax) { vmin = std::numeric_limits::max(); vmax = std::numeric_limits::lowest(); bool none = true; for (Iterator v = start; v !=end; ++v) { if (!std::isnan(*v)) { if (*v >= lmin && *v <= lmax) { if (*v > vmax) { vmax = *v; none = false; } if (*v < vmin) { vmin = *v; } } } } if (none) { vmin = NAN; vmax = NAN; } } template void minmax(Iterator start, Iterator end, double &vmin, double &vmax) { vmin = std::numeric_limits::max(); vmax = std::numeric_limits::lowest(); bool none = true; for (Iterator v = start; v !=end; ++v) { if (!std::isnan(*v)) { if (*v > vmax) { vmax = *v; none = false; } if (*v < vmin) { vmin = *v; } } } if (none) { vmin = NAN; vmax = NAN; } } terra/src/progress_bar_simple.hpp0000644000175000017500000000467314201035750017071 0ustar nileshnilesh/* * simple_progress_bar.hpp * * A class that display a progress bar * * Author: karl.forner@gmail.com * */ #ifndef _RcppProgress_SIMPLE_PROGRESS_BAR_HPP #define _RcppProgress_SIMPLE_PROGRESS_BAR_HPP #include "progress_bar.hpp" #include // for unices only #if !defined(WIN32) && !defined(__WIN32) && !defined(__WIN32__) #include #endif class SimpleProgressBar: public ProgressBar{ public: // ====== LIFECYCLE ===== /** * Main constructor */ SimpleProgressBar() { reset(); } ~SimpleProgressBar() {} public: // ===== main methods ===== void display() { // REprintf("0%% 10 20 30 40 50 60 70 80 90 100%%\n"); // REprintf("[----|----|----|----|----|----|----|----|----|----|\n"); // REprintf("[----|----|----|----|----|----|----|----|----|----|"); REprintf("=====|====|====|====|====|====|====|====|====|===="); REprintf("\r"); flush_console(); } // will finalize display if needed void update(float progress) { _update_ticks_display(progress); if (_ticks_displayed >= _max_ticks) _finalize_display(); } void end_display() { update(1); reset(); } void reset() { _max_ticks = 50; _ticks_displayed = 0; _finalized = false; } protected: // ==== other instance methods ===== // update the ticks display corresponding to progress void _update_ticks_display(float progress) { int nb_ticks = _compute_nb_ticks(progress); int delta = nb_ticks - _ticks_displayed; if (delta > 0) { _display_ticks(delta); _ticks_displayed = nb_ticks; } } void _finalize_display() { if (_finalized) return; // REprintf("|\n"); REprintf("\r "); REprintf("\n\r"); flush_console(); _finalized = true; } int _compute_nb_ticks(float progress) { return int(progress * _max_ticks); } void _display_ticks(int nb) { for (int i = 0; i < nb; ++i) { // REprintf("*"); REprintf("-"); R_FlushConsole(); } } // N.B: does nothing on windows void flush_console() { #if !defined(WIN32) && !defined(__WIN32) && !defined(__WIN32__) R_FlushConsole(); #endif } private: int _max_ticks; // the total number of ticks to print int _ticks_displayed; // the nb of ticks already displayed bool _finalized; }; #endif terra/src/spatRasterMultiple.h0000644000175000017500000001626214201035750016331 0ustar nileshnilesh// Copyright (c) 2018-2020 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include "spatRaster.h" // A collection of (perhaps non matching) SpatRasters class SpatRasterCollection { public: virtual ~SpatRasterCollection(){} SpatMessages msg; SpatRasterCollection deepCopy() { return *this; } void setError(std::string s) { msg.setError(s); } void addWarning(std::string s) { msg.addWarning(s); } bool has_error() { return msg.has_error; } bool has_warning() { return msg.has_warning; } std::string getWarnings() { return msg.getWarnings(); } std::string getError() { return msg.getError(); } std::vector ds; SpatRasterCollection() {}; SpatRasterCollection(size_t n) { ds.resize(n); }; size_t size() { return ds.size(); } void resize(size_t n) { ds.resize(n); } void push_back(SpatRaster r) { ds.push_back(r); }; void erase(size_t i) { if (i < ds.size()) { ds.erase(ds.begin()+i); } } SpatRaster merge(SpatOptions &opt); SpatRaster morph(SpatRaster &x, SpatOptions &opt); SpatRaster mosaic(std::string fun, SpatOptions &opt); SpatRaster summary(std::string fun, SpatOptions &opt); }; // A class for "sub-datasets" class SpatRasterStack { public: virtual ~SpatRasterStack(){} SpatRasterStack deepCopy() { return *this; } SpatMessages msg; void setError(std::string s) { msg.setError(s); } void addWarning(std::string s) { msg.addWarning(s); } bool has_error() { return msg.has_error; } bool has_warning() { return msg.has_warning; } std::string getWarnings() { return msg.getWarnings();} std::string getError() { return msg.getError();} std::vector ds; std::vector names; std::vector long_names; std::vector units; SpatRasterStack() {}; SpatRasterStack(std::string fname, std::vector ids, bool useids); SpatRasterStack(SpatRaster r, std::string name, std::string longname, std::string unit, bool warn=false) { push_back(r, name, longname, unit, warn); }; std::vector>> extractXY(std::vector &x, std::vector &y, std::string method); std::vector>> extractCell(std::vector &cell); std::vector>>> extractVector(SpatVector v, bool touches, std::string method, SpatOptions &opt); std::vector get_names() { return names; }; void set_names(std::vector nms) { if (nms.size() == ds.size()) { names = nms; } } std::vector get_longnames() { return long_names; }; void set_longnames(std::vector nms) { if (nms.size() == ds.size()) { long_names = nms; } } std::vector get_units() { return units; }; void set_units(std::vector u) { if (u.size() == ds.size()) { units = u; } } bool readStart() { for (auto& x : ds) { if (!x.readStart()) return false; } return true; } bool readStop() { for (auto& x : ds) { if (!x.readStop()) return false; } return true; } unsigned nsds() { return ds.size(); } unsigned nrow() { if (ds.size() > 0) { return ds[0].nrow(); } else { return 0; } } unsigned ncol() { if (ds.size() > 0) { return ds[0].ncol(); } else { return 0; } } std::vector nlyr() { std::vector out; if (ds.size() > 0) { out.reserve(ds.size()); for (size_t i=0; i 0) { return ds[0].getSRS(s); } else { return ""; } } bool push_back(SpatRaster r, std::string name, std::string longname, std::string unit, bool warn) { if (ds.size() > 0) { if (!r.compare_geom(ds[0], false, false, true, true, true, false)) { // if (!ds[0].compare_geom(r, false, false, true, true, false, false)) { if (warn) { addWarning(r.msg.getError() +" (" + name + ")"); return true; } else { setError(r.msg.getError() +" (" + name + ")"); return false; } } } ds.push_back(r); names.push_back(name); long_names.push_back(longname); units.push_back(unit); if (r.hasWarning()) { for (size_t i=0; i x) { SpatRasterStack out; for (size_t i=0; i ff = opt.get_filenames(); if (ff.size() != ds.size()) { opt.set_filenames({""}); opt.ncopies *= ds.size(); } for (size_t i=0; i (ds.size()-1)) { setError("invalid index"); return; } if (ds.size() == 0) { setError("cannot replace on empty stack"); return; } if (!ds[0].compare_geom(x, false, false, true, true, false, false)) { setError("extent does not match"); return; } ds[i] = x; names[i] = x.getNames()[0]; long_names[i] = x.getLongSourceNames()[0]; units[i] = x.getUnit()[0]; } SpatRaster collapse() { SpatRaster out; if (ds.size() > 0) { out = ds[0]; for (size_t i=1; i add, bool narm, SpatOptions &opt); SpatRaster summary(std::string fun, bool narm, SpatOptions &opt); }; terra/src/progress_bar.hpp0000644000175000017500000000121714201035750015507 0ustar nileshnilesh/* * progress_bar.hpp * * An abstract class for classes that display a progress bar * * Author: karl.forner@gmail.com * */ #ifndef _RcppProgress_PROGRESS_BAR_HPP #define _RcppProgress_PROGRESS_BAR_HPP class ProgressBar { public: // subclasses should not rely on the destructor to finalize the display virtual ~ProgressBar() = 0; // start the display. It will be updated by subsequent calls to update() virtual void display() = 0; // update if needed the display virtual void update(float progress) = 0; // finalize the display virtual void end_display() = 0; }; inline ProgressBar::~ProgressBar() {} #endif terra/src/read.cpp0000644000175000017500000002346414201035750013735 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include "spatRaster.h" bool SpatRaster::readStart() { //if (!valid_sources(true, true)) { // return false; //} for (size_t i=0; i> &v, BlockSize bs, unsigned i) { std::vector x; readValues(x, bs.row[i], bs.nrows[i], 0, ncol()); v.resize(nlyr()); size_t off = bs.nrows[i] * ncol(); for (size_t i=0; i(x.begin()+(i*off), x.begin()+((i+1)*off)); } } // BIP std::vector SpatRaster::readBlockIP(BlockSize bs, unsigned i) { std::vector x; readValues(x, bs.row[i], bs.nrows[i], 0, ncol()); std::vector v(x.size()); size_t off = bs.nrows[i] * ncol(); size_t nl = nlyr(); for (size_t i=0; i lyr = std::vector(x.begin()+(i*off), x.begin()+((i+1)*off)); for (size_t j=0; j &out, size_t src, size_t row, size_t nrows, size_t col, size_t ncols){ size_t nl = source[src].nlyr; if (source[src].hasWindow) { row += source[src].window.off_row; col += source[src].window.off_col; size_t endrow = row + nrows; size_t endcol = col + ncols; size_t nc = source[src].window.full_ncol; double ncells = source[src].window.full_nrow * nc; for (size_t lyr=0; lyr < nl; lyr++) { size_t add = ncells * lyr; for (size_t r = row; r < endrow; r++) { size_t off = add + r * nc; out.insert(out.end(), source[src].values.begin()+off+col, source[src].values.begin()+off+endcol); } } /* else if (source[0].window.expanded) { unsigned add = ncells * lyr; std::vector v1(source[0].window.expand[0] * ncols, NAN); out.insert(out.end(), v1.begin(), v1.end()); v1.resize(source[0].window.expand[1], NAN); std::vector v2(source[0].window.expand[2], NAN); for (size_t r = wrow; r < endrow; r++) { unsigned a = add + r * source[0].window.full_ncol; out.insert(out.end(), v1.begin(), v1.end()); out.insert(out.end(), source[src].values.begin()+a+wcol, source[src].values.begin()+a+endcol); out.insert(out.end(), v2.begin(), v2.end()); } v1.resize(source[0].window.expand[3] * ncols, NAN); out.insert(out.end(), v1.begin(), v1.end()); } */ } else { // no window size_t nc = ncol(); if (row==0 && nrows==nrow() && col==0 && ncols==nc) { out.insert(out.end(), source[src].values.begin(), source[src].values.end()); } else { double ncells = ncell(); if (col==0 && ncols==nc) { for (size_t lyr=0; lyr < nl; lyr++) { size_t add = ncells * lyr; size_t a = add + row * nc; size_t b = a + nrows * nc; out.insert(out.end(), source[src].values.begin()+a, source[src].values.begin()+b); } } else { size_t endrow = row + nrows; size_t endcol = col + ncols; for (size_t lyr=0; lyr < nl; lyr++) { size_t add = ncells * lyr; for (size_t r = row; r < endrow; r++) { size_t a = add + r * nc; out.insert(out.end(), source[src].values.begin()+a+col, source[src].values.begin()+a+endcol); } } } } } } std::vector SpatRaster::readValuesR(size_t row, size_t nrows, size_t col, size_t ncols){ std::vector out; if (((row + nrows) > nrow()) || ((col + ncols) > ncol())) { setError("invalid rows/columns"); return out; } //row = std::min(std::max(size_t(0), row), nrow()-1); //col = std::min(std::max(size_t(0), col), ncol()-1); //nrows = std::max(size_t(1), std::min(nrows, nrow()-row)); //ncols = std::max(size_t(1), std::min(ncols, ncol()-col)); if ((nrows==0) | (ncols==0)) { return out; } if (!hasValues()) { out.resize(nrows * ncols * nlyr(), NAN); addWarning("raster has no values"); return out; // or NAs? } unsigned n = nsrc(); out.reserve(nrows * ncols * nlyr()); for (size_t src=0; src gout; readChunkGDAL(gout, src, source[0].window.off_row, nrows, source[0].window.off_col, ncols); size_t rrow = row + source[0].window.off_row; size_t rcol = col + source[0].window.off_col; unsigned endrow = rrow + nrows; unsigned endcol = rcol + ncols; unsigned ncells = source[0].window.full_nrow * source[0].window.full_ncol; unsigned nl = source[src].nlyr; for (size_t lyr=0; lyr < nl; lyr++) { unsigned add = ncells * lyr; std::vector v1(source[0].window.expand[0] * ncols, NAN); out.insert(out.end(), v1.begin(), v1.end()); v1.resize(source[0].window.expand[1], NAN); std::vector v2(source[0].window.expand[2], NAN); for (size_t r = rrow; r < endrow; r++) { unsigned a = add + r * source[0].window.full_ncol; out.insert(out.end(), v1.begin(), v1.end()); out.insert(out.end(), gout.begin()+a+rcol, gout.begin()+a+endcol); out.insert(out.end(), v2.begin(), v2.end()); } v1.resize(source[0].window.expand[3] * ncols, NAN); out.insert(out.end(), v1.begin(), v1.end()); } } */ readChunkGDAL(out, src, row, nrows, col, ncols); #endif // useGDAL } } return out; } void SpatRaster::readValues(std::vector &out, size_t row, size_t nrows, size_t col, size_t ncols){ if (((row + nrows) > nrow()) || ((col + ncols) > ncol())) { setError("invalid rows/columns"); return; } if ((nrows==0) | (ncols==0)) { return; } if (!hasValues()) { out.resize(nrows * ncols * nlyr(), NAN); addWarning("raster has no values"); return; // or NAs? } unsigned n = nsrc(); out.resize(0); out.reserve(nrows * ncols * nlyr()); for (size_t src=0; src 0) { if (!source[0].combine_sources(source[src])) { setError("could not combine sources"); return false; } source[src].values.resize(0); } } readStop(); if (n>1) source.resize(1); return true; } std::vector SpatRaster::getValues(long lyr, SpatOptions &opt) { std::vector out; bool hw = false; for (size_t i=0; i fvals = readValuesGDAL(src, 0, nrow(), 0, ncol()); out.insert(out.end(), fvals.begin(), fvals.end()); #endif // useGDAL } } } else { // read one lyr std::vector sl = findLyr(lyr); unsigned src=sl[0]; if (source[src].memory) { size_t start = sl[1] * ncell(); out = std::vector(source[src].values.begin()+start, source[src].values.begin()+start+ncell()); } else { #ifdef useGDAL out = readValuesGDAL(src, 0, nrow(), 0, ncol(), sl[1]); #endif // useGDAL } } return out; } bool SpatRaster::getValuesSource(size_t src, std::vector &out) { unsigned n = nsrc(); if (src > n) { return false; } bool hw = false; for (size_t i=0; i(source[src].values.begin(), source[src].values.end()); } else { #ifdef useGDAL out = readValuesGDAL(src, 0, nrow(), 0, ncol()); #endif // useGDAL } return true; } terra/src/vecmath.cpp0000644000175000017500000000462014201035750014442 0ustar nileshnilesh// Copyright (c) 2018-2021 Robert J. Hijmans // // This file is part of the "spat" library. // // spat is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // spat is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with spat. If not, see . #include #include #include #include #include "vecmath.h" bool haveFun(std::string fun) { std::vector f {"sum", "mean", "median", "modal", "which", "which.min", "which.max", "min", "max", "prod", "any", "all", "sd", "std", "first"}; auto it = std::find(f.begin(), f.end(), fun); if (it == f.end()) { return false; } return true; } std::function&, bool)> getFun(std::string fun) { std::function&, bool)> theFun; if (fun == "mean") { theFun = vmean; } else if (fun == "sum") { theFun = vsum; } else if (fun == "sum2") { theFun = vsum2; } else if (fun == "min") { theFun = vmin; } else if (fun == "max") { theFun = vmax; } else if (fun == "median") { theFun = vmedian; } else if (fun == "modal") { theFun = vmodal; } else if (fun == "prod") { theFun = vprod; } else if (fun == "which") { theFun = vwhich; } else if (fun == "which.min") { theFun = vwhichmin; } else if (fun == "which.max") { theFun = vwhichmax; } else if (fun == "any") { theFun = vany; } else if (fun == "all") { theFun = vall; } else if (fun == "sd") { theFun = vsd; } else if (fun == "std") { theFun = vsdpop; } else if (fun == "first") { theFun = vfirst; } else { theFun = vmean; } return theFun; } bool ball(const std::vector& v) { for (size_t i=0; i& v) { for (size_t i=0; i. #include "spatDataframe.h" #include #include #include #include "NA.h" #include "string_utils.h" SpatDataFrame::SpatDataFrame() {} SpatDataFrame SpatDataFrame::skeleton() { SpatDataFrame out; out.names = names; out.itype = itype; out.iplace = iplace; out.dv = std::vector>(dv.size()); out.iv = std::vector>(iv.size()); out.sv = std::vector>(sv.size()); return out; } std::vector SpatDataFrame::getD(unsigned i) { unsigned j = iplace[i]; return dv[j]; } double SpatDataFrame::getDvalue(unsigned i, unsigned j) { j = iplace[j]; return dv[j][i]; } std::vector SpatDataFrame::getI(unsigned i) { unsigned j = iplace[i]; return iv[j]; } long SpatDataFrame::getIvalue(unsigned i, unsigned j) { j = iplace[j]; return iv[j][i]; } std::vector SpatDataFrame::getS(unsigned i) { unsigned j = iplace[i]; return sv[j]; } std::string SpatDataFrame::getSvalue(unsigned i, unsigned j) { j = iplace[j]; return sv[j][i]; } SpatDataFrame SpatDataFrame::subset_rows(unsigned i) { std::vector r = { i }; return subset_rows(r); } SpatDataFrame SpatDataFrame::subset_rows(std::vector range) { SpatDataFrame out; unsigned nr = nrow(); if (range.size() > 0) { for (int i = range.size(); i>0; i--) { if (range[i-1] > nr) { range.erase(range.begin() + i-1); } } } out.names = names; out.itype = itype; out.iplace = iplace; out.dv.resize(dv.size()); out.iv.resize(iv.size()); out.sv.resize(sv.size()); out.dv.reserve(range.size()); out.iv.reserve(range.size()); out.sv.reserve(range.size()); for (size_t i=0; i < range.size(); i++) { for (size_t j=0; j < dv.size(); j++) { out.dv[j].push_back(dv[j][range[i]]); } for (size_t j=0; j < iv.size(); j++) { out.iv[j].push_back(iv[j][range[i]]); } for (size_t j=0; j < sv.size(); j++) { out.sv[j].push_back(sv[j][range[i]]); } } return out; } SpatDataFrame SpatDataFrame::subset_rows(std::vector range) { std::vector r(range.begin(), range.end()); return subset_rows(r); } SpatDataFrame SpatDataFrame::subset_cols(unsigned i) { std::vector c = { i }; return subset_cols(c); } SpatDataFrame SpatDataFrame::subset_cols(std::vector range) { SpatDataFrame out; unsigned dcnt=0; unsigned icnt=0; unsigned scnt=0; for (size_t i=0; i < range.size(); i++) { if (range[i] < 0 || range[i] >= ncol()) { out.setError("invalid column"); return out; } unsigned j = range[i]; unsigned p = iplace[j]; out.names.push_back(names[j]); if (itype[j] == 0) { out.dv.push_back(dv[p]); out.iplace.push_back(dcnt); out.itype.push_back(0); dcnt++; } else if (itype[j] == 1) { out.iv.push_back(iv[p]); out.iplace.push_back(icnt); out.itype.push_back(1); icnt++; } else { out.sv.push_back(sv[p]); out.iplace.push_back(scnt); out.itype.push_back(2); scnt++; } } return out; } unsigned SpatDataFrame::ncol() { return itype.size(); } unsigned SpatDataFrame::nrow() { unsigned n; if (itype.size() == 0) { n = 0; } else { if (itype[0] == 0) { n = dv[0].size(); } else if (itype[0] == 1) { n = iv[0].size(); } else { n = sv[0].size(); } } return n; } void SpatDataFrame::add_row() { for (size_t i=0; i < dv.size(); i++) { dv[i].push_back(NAN); } long longNA = NA::value; for (size_t i=0; i < iv.size(); i++) { iv[i].push_back(longNA); } for (size_t i=0; i < sv.size(); i++) { sv[i].push_back(NAS); } } void SpatDataFrame::add_rows(size_t n) { size_t s = nrow() + n; for (size_t i=0; i < dv.size(); i++) { dv[i].resize(s, NAN); } long longNA = NA::value; for (size_t i=0; i < iv.size(); i++) { iv[i].resize(s, longNA); } for (size_t i=0; i < sv.size(); i++) { sv[i].resize(s, NAS); } } void SpatDataFrame::reserve(unsigned n) { for (size_t i=0; i::value; for (size_t i=0; i r) { if (r.size() == 0) return; //sort(r.begin(), r.end(), std::greater()); sort(r.begin(), r.end()); r.erase(std::unique(r.begin(), r.end()), r.end()); std::reverse(r.begin(), r.end()); for (size_t j=0; j x, std::string name) { unsigned nr = nrow(); if ((nr != 0) & (nr != x.size())) return false; iplace.push_back(dv.size()); itype.push_back(0); names.push_back(name); dv.push_back(x); return true; } bool SpatDataFrame::remove_column(int i) { if ((i < 0) | ((size_t)i > ncol())) { return false; } size_t dtype = itype[i]; size_t place = iplace[i]; size_t ii = i; if (ii < (iplace.size()-1)) { for (size_t j=i+1; j x, std::string name) { unsigned nr = nrow(); if ((nr != 0) & (nr != x.size())) return false; iplace.push_back(iv.size()); itype.push_back(1); names.push_back(name); iv.push_back(x); return true; } bool SpatDataFrame::add_column(std::vector x, std::string name) { std::vector v(x.begin(), x.end()); return add_column(v, name); } bool SpatDataFrame::add_column(std::vector x, std::string name) { unsigned nr = nrow(); if ((nr != 0) & (nr != x.size())) return false; iplace.push_back(sv.size()); itype.push_back(2); names.push_back(name); sv.push_back(x); return true; } void SpatDataFrame::add_column(unsigned dtype, std::string name) { unsigned nr = nrow(); if (dtype == 0) { std::vector dins(nr, NAN); iplace.push_back(dv.size()); dv.push_back(dins); } else if (dtype == 1) { long longNA = NA::value; std::vector iins(nr, longNA); iplace.push_back(iv.size()); iv.push_back(iins); } else { std::vector sins(nr, NAS); iplace.push_back(sv.size()); sv.push_back(sins); } itype.push_back(dtype); names.push_back(name); } bool SpatDataFrame::cbind(SpatDataFrame &x) { unsigned nc = x.ncol(); std::vector nms = x.names; for (size_t i=0; i d = x.getD(i); if (!add_column(d, nms[i])) return false; } else if (x.itype[i] == 1) { std::vector d = x.getI(i); if (!add_column(d, nms[i])) return false; } else { std::vector d = x.getS(i); if (!add_column(d, nms[i])) return false; } } return true; } bool SpatDataFrame::rbind(SpatDataFrame &x) { size_t nr1 = nrow(); size_t nr2 = x.nrow(); // size_t nc1 = ncol(); size_t nc2 = x.ncol(); //first add new columns std::vector nms = names; for (size_t i=0; i SpatDataFrame::get_names() { return names; } void SpatDataFrame::set_names(std::vector nms){ if (ncol() == nms.size()) { make_valid_names(nms); make_unique_names(nms); names = nms; } else { setError("number of names is not correct"); } } std::vector SpatDataFrame::get_datatypes() { std::vector types = {"double", "long", "string"}; std::vector stype(itype.size()); for (size_t i=0; i types = {"double", "long", "string"}; return types[i]; } std::string SpatDataFrame::get_datatype(int field) { if ((field < 0) || (field > (int)(ncol()-1))) return ""; std::vector types = {"double", "long", "string"}; return types[itype[field]]; } bool SpatDataFrame::field_exists(std::string field) { return is_in_vector(field, get_names()); } int SpatDataFrame::get_fieldindex(std::string field) { return where_in_vector(field, get_names(), false); } // only doing this for one column for now SpatDataFrame SpatDataFrame::unique(int col) { SpatDataFrame out = subset_cols(col); if (out.hasError()) return out; if (out.itype[0] == 0) { size_t sz = nrow(); out.dv[0].erase(std::remove_if(out.dv[0].begin(), out.dv[0].end(), [](const double& value) { return std::isnan(value); }), out.dv[0].end()); bool hasNAN = sz > out.dv[0].size(); std::sort(out.dv[0].begin(), out.dv[0].end()); out.dv[0].erase(std::unique(out.dv[0].begin(), out.dv[0].end()), out.dv[0].end()); if (hasNAN) out.dv[0].push_back(NAN); } else if (out.itype[0] == 1) { std::sort(out.iv[0].begin(), out.iv[0].end()); out.iv[0].erase(std::unique(out.iv[0].begin(), out.iv[0].end()), out.iv[0].end()); } else { std::sort(out.sv[0].begin(), out.sv[0].end()); out.sv[0].erase(std::unique(out.sv[0].begin(), out.sv[0].end()), out.sv[0].end()); } return out; } std::vector SpatDataFrame::getIndex(int col, SpatDataFrame &x) { size_t nd = nrow(); x = unique(col); size_t nu = x.nrow(); std::vector idx(nd, -1); size_t ccol = iplace[col]; if (x.itype[0] == 0) { for (size_t i=0; i SpatDataFrame::as_double(size_t v) { std::vector out; if (v >= ncol()) { setError("attempting to read a column that does not exist"); return out; } if (itype[v] > 1) { setError("as_double only available for long and double"); return out; } size_t j = iplace[v]; if (itype[v] == 0) return dv[j]; // if (itype[v] == 1) { out.reserve(nrow()); for (size_t i=0; i SpatDataFrame::as_long(size_t v) { std::vector out; if (v >= ncol()) { setError("attempting to read a column that does not exist"); return out; } if (itype[v] > 1) { setError("as_long only available for long and double"); return out; } size_t j = iplace[v]; if (itype[v] == 1) return iv[j]; // if (itype[v] == 0) { out.reserve(nrow()); for (size_t i=0; i SpatDataFrame::as_string(size_t v) { std::vector out; if (v >= ncol()) { setError("attempting to read a column that does not exist"); return out; } std::string dt = get_datatype(v); size_t j = iplace[v]; if (dt == "string") return sv[j]; out.reserve(nrow()); if (dt == "double") { for (size_t i=0; i/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="src/write_ogr.cpp" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS GEOS_CONFIG PROJ_LIBS PROJ_CPPFLAGS SQLITE3_LIBS EGREP GREP CPP OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC PKG_LIBS PKG_CPPFLAGS GDAL_CONFIG target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_gdal_config with_data_copy with_proj_data with_sqlite3_lib with_proj_include with_proj_api with_proj_lib with_proj_share with_geos_config ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gdal-config=GDAL_CONFIG the location of gdal-config --with-data-copy=yes/no local copy of data directories in package, default no --with-proj-data=DIR location of PROJ data directory --with-sqlite3-lib=LIB_PATH the location of sqlite3 libraries --with-proj-include=DIR location of proj header files --with-proj-api=yes/no use the deprecated proj_api.h even when PROJ 6 is available; default no --with-proj-lib=LIB_PATH the location of proj libraries --with-proj-share=SHARE_PATH the location of proj metadata files --with-geos-config=GEOS_CONFIG the location of geos-config Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu : ${R_HOME=`R RHOME`} if test -z "${R_HOME}"; then echo "could not determine R_HOME" exit 1 fi RBIN="${R_HOME}/bin/R" # https://github.com/r-spatial/sf/issues/1054: # RVER=`"${RBIN}" --version | head -1 | cut -f3 -d" "` RSCRIPT="${R_HOME}/bin/Rscript" RVER=`"${RSCRIPT}" -e 'writeLines(paste(sep=".", base::version$major, base::version$minor))'` RVER_MAJOR=`echo ${RVER} | cut -f1 -d"."` RVER_MINOR=`echo ${RVER} | cut -f2 -d"."` RVER_PATCH=`echo ${RVER} | cut -f3 -d"."` if test $RVER_MAJOR = "development"; then CXX11=`"${RBIN}" CMD config CXX11` CXX11STD=`"${RBIN}" CMD config CXX11STD` else if test $RVER_MAJOR -lt 3 -o $RVER_MAJOR -eq 3 -a $RVER_MINOR -lt 3; then as_fn_error $? "terra is not compatible with R versions before 3.3.0" "$LINENO" 5 else if test $RVER_MAJOR -eq 3 -a $RVER_MINOR -eq 3; then CXX11=`"${RBIN}" CMD config CXX1X` CXX11STD=`"${RBIN}" CMD config CXX1XSTD` else CXX11=`"${RBIN}" CMD config CXX11` CXX11STD=`"${RBIN}" CMD config CXX11STD` fi fi fi # pick all flags for testing from R : ${CC=`"${RBIN}" CMD config CC`} : ${CXX=${CXX11} ${CXX11STD}} : ${CFLAGS=`"${RBIN}" CMD config CFLAGS`} : ${CPPFLAGS=`"${RBIN}" CMD config CPPFLAGS`} : ${CXXFLAGS=`"${RBIN}" CMD config CXXFLAGS`} : ${LDFLAGS=`"${RBIN}" CMD config LDFLAGS`} # AC_SUBST([CC],["clang"]) # AC_SUBST([CXX],["clang++"]) { $as_echo "$as_me:${as_lineno-$LINENO}: CC: ${CC}" >&5 $as_echo "$as_me: CC: ${CC}" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: CXX: ${CXX}" >&5 $as_echo "$as_me: CXX: ${CXX}" >&6;} # AC_MSG_NOTICE([${PACKAGE_NAME}: ${PACKAGE_VERSION}]) #GDAL GDAL_CONFIG="gdal-config" GDAL_CONFIG_SET="no" # Check whether --with-gdal-config was given. if test "${with_gdal_config+set}" = set; then : withval=$with_gdal_config; gdal_config=$withval fi if test -n "$gdal_config" ; then GDAL_CONFIG_SET="yes" GDAL_CONFIG="${gdal_config}" { $as_echo "$as_me:${as_lineno-$LINENO}: gdal-config set to $GDAL_CONFIG" >&5 $as_echo "$as_me: gdal-config set to $GDAL_CONFIG" >&6;} fi if test "$GDAL_CONFIG_SET" = "no" ; then # Extract the first word of ""$GDAL_CONFIG"", so it can be a program name with args. set dummy "$GDAL_CONFIG"; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GDAL_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $GDAL_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_GDAL_CONFIG="$GDAL_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GDAL_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_GDAL_CONFIG" && ac_cv_path_GDAL_CONFIG=""no"" ;; esac fi GDAL_CONFIG=$ac_cv_path_GDAL_CONFIG if test -n "$GDAL_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GDAL_CONFIG" >&5 $as_echo "$GDAL_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$GDAL_CONFIG" = "no" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "gdal-config not found or not executable." "$LINENO" 5 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking gdal-config exists" >&5 $as_echo_n "checking gdal-config exists... " >&6; } if test -r "${GDAL_CONFIG}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "gdal-config not found - configure argument error." "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking gdal-config executable" >&5 $as_echo_n "checking gdal-config executable... " >&6; } if test -x "${GDAL_CONFIG}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "gdal-config not executable." "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking gdal-config usability" >&5 $as_echo_n "checking gdal-config usability... " >&6; } if test `${GDAL_CONFIG} --version`; then GDAL_CPPFLAGS=`${GDAL_CONFIG} --cflags` GDAL_VERSION=`${GDAL_CONFIG} --version` GDAL_LIBS=`${GDAL_CONFIG} --libs` GDAL_DEP_LIBS=`${GDAL_CONFIG} --dep-libs` GDAL_DATADIR=`${GDAL_CONFIG} --datadir` { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } echo "Error: gdal-config not found" echo "The gdal-config script distributed with GDAL could not be found." echo "If you have not installed the GDAL libraries, you can" echo "download the source from http://www.gdal.org/" echo "If you have installed the GDAL libraries, then make sure that" echo "gdal-config is in your path. Try typing gdal-config at a" echo "shell prompt and see if it runs. If not, use:" echo " --configure-args='--with-gdal-config=/usr/local/bin/gdal-config'" echo "with appropriate values for your installation." echo "" exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: GDAL: ${GDAL_VERSION}" >&5 $as_echo "$as_me: GDAL: ${GDAL_VERSION}" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking GDAL version >= 2.0.1" >&5 $as_echo_n "checking GDAL version >= 2.0.1... " >&6; } GDAL_MAJ_VER=`echo $GDAL_VERSION | cut -d "." -f1` if test ${GDAL_MAJ_VER} -lt 2 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "terra is not compatible with GDAL versions below 2.0.1" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi INLIBS="${LIBS}" INCPPFLAGS="${CPPFLAGS}" INPKG_CPPFLAGS="${PKG_CPPFLAGS}" INPKG_LIBS="${PKG_LIBS}" PKG_CPPFLAGS="${INPKG_CPPFLAGS} ${GDAL_CPPFLAGS}" PKG_LIBS="${INPKG_LIBS} ${GDAL_LIBS}" # honor PKG_xx overrides # for CPPFLAGS we will superfluously double R's flags # since we'll set PKG_CPPFLAGS with this, but that shouldn't hurt CPPFLAGS="${INCPPFLAGS} ${PKG_CPPFLAGS}" gdalok=yes ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in gdal.h do : ac_fn_c_check_header_mongrel "$LINENO" "gdal.h" "ac_cv_header_gdal_h" "$ac_includes_default" if test "x$ac_cv_header_gdal_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GDAL_H 1 _ACEOF else gdalok=no fi done if test "${gdalok}" = no; then as_fn_error $? "gdal.h not found in given locations." "$LINENO" 5 fi NEED_DEPS=no LIBS="${INLIBS} ${PKG_LIBS}" cat > gdal_test.cpp <<_EOCONF #include #ifdef __cplusplus extern "C" { #endif int main() { GDALAllRegister(); } #ifdef __cplusplus } #endif _EOCONF { $as_echo "$as_me:${as_lineno-$LINENO}: checking GDAL: linking with --libs only" >&5 $as_echo_n "checking GDAL: linking with --libs only... " >&6; } ${CXX} ${CPPFLAGS} -o gdal_test gdal_test.cpp ${LIBS} 2> errors.txt if test `echo $?` -ne 0 ; then gdalok=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi if test "${gdalok}" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking GDAL: linking with --libs and --dep-libs" >&5 $as_echo_n "checking GDAL: linking with --libs and --dep-libs... " >&6; } LIBS="${LIBS} ${GDAL_DEP_LIBS}" gdalok=yes ${CXX} ${CPPFLAGS} -o gdal_test gdal_test.cpp ${LIBS} 2>> errors.txt if test `echo $?` -ne 0 ; then gdalok=no fi if test "${gdalok}" = yes; then NEED_DEPS=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test "${gdalok}" = no; then cat errors.txt { $as_echo "$as_me:${as_lineno-$LINENO}: Install failure: compilation and/or linkage problems." >&5 $as_echo "$as_me: Install failure: compilation and/or linkage problems." >&6;} as_fn_error $? "GDALAllRegister not found in libgdal." "$LINENO" 5 fi rm -f gdal_test errors.txt gdal_test.cpp GDAL_GE_250="no" GDAL_MAJ_VER=`echo $GDAL_VERSION | cut -d "." -f1` GDAL_MOD_VER=`echo $GDAL_VERSION | cut -d "." -f2` if test "${GDAL_MAJ_VER}" = 2 ; then if test "${GDAL_MOD_VER}" -ge 5 ; then GDAL_GE_250="yes" fi else if test "${GDAL_MAJ_VER}" -ge 3 ; then GDAL_GE_250="yes" fi fi GDAL_DATA_TEST_FILE="${GDAL_DATADIR}/pcs.csv" { $as_echo "$as_me:${as_lineno-$LINENO}: checking GDAL: ${GDAL_DATADIR}/pcs.csv readable" >&5 $as_echo_n "checking GDAL: ${GDAL_DATADIR}/pcs.csv readable... " >&6; } if test -r "${GDAL_DATA_TEST_FILE}" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test "${GDAL_GE_250}" = "no" ; then as_fn_error $? "pcs.csv not found in GDAL data directory." "$LINENO" 5 fi fi # Optional local copy of GDAL datadir and PROJ_LIB data_copy=no if test "${PROJ_GDAL_DATA_COPY}" ; then data_copy=yes { $as_echo "$as_me:${as_lineno-$LINENO}: PROJ_GDAL_DATA_COPY used." >&5 $as_echo "$as_me: PROJ_GDAL_DATA_COPY used." >&6;} else # Check whether --with-data-copy was given. if test "${with_data_copy+set}" = set; then : withval=$with_data_copy; data_copy=$withval fi fi if test "${data_copy}" = "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: Copy data for:" >&5 $as_echo "$as_me: Copy data for:" >&6;} proj_lib0="${PROJ_LIB}" # Check whether --with-proj-data was given. if test "${with_proj_data+set}" = set; then : withval=$with_proj_data; proj_lib1=$withval fi if test -n "${proj_lib0}" ; then proj_lib="${proj_lib0}" else proj_lib="${proj_lib1}" fi if test -n "${proj_lib}" ; then if test -d "${proj_lib}" ; then cp -r "${proj_lib}" "${R_PACKAGE_DIR}" { $as_echo "$as_me:${as_lineno-$LINENO}: PROJ: ${proj_lib}" >&5 $as_echo "$as_me: PROJ: ${proj_lib}" >&6;} else as_fn_error $? "PROJ data files not found; set environment variable PROJ_LIB=DIR or --with-proj-data=DIR." "$LINENO" 5 fi else as_fn_error $? "PROJ data files not found; set environment variable PROJ_LIB=DIR or --with-proj-data=DIR." "$LINENO" 5 fi if test -d "${GDAL_DATADIR}" ; then cp -r "${GDAL_DATADIR}" "${R_PACKAGE_DIR}" { $as_echo "$as_me:${as_lineno-$LINENO}: GDAL: ${GDAL_DATADIR}" >&5 $as_echo "$as_me: GDAL: ${GDAL_DATADIR}" >&6;} else as_fn_error $? "GDAL data files not found." "$LINENO" 5 fi fi # # test whether PROJ is available to gdal: # gdal_has_proj=no cat > gdal_proj.cpp <<_EOCONF #include #include #include int main(int argc, char *argv[]) { OGRSpatialReference *dest = new OGRSpatialReference; OGRSpatialReference *src = new OGRSpatialReference; src->importFromEPSG(4326); dest->importFromEPSG(3857); OGRCoordinateTransformation *ct = OGRCreateCoordinateTransformation(src, dest); return(ct == NULL); // signals PROJ is not available through gdal } _EOCONF { $as_echo "$as_me:${as_lineno-$LINENO}: checking GDAL: checking whether PROJ is available for linking:" >&5 $as_echo_n "checking GDAL: checking whether PROJ is available for linking:... " >&6; } ${CXX} ${CPPFLAGS} -o gdal_proj gdal_proj.cpp ${LIBS} 2> errors.txt if test `echo $?` -ne 0 ; then gdal_has_proj=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else gdal_has_proj=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi if test "${gdal_has_proj}" = no; then cat errors.txt { $as_echo "$as_me:${as_lineno-$LINENO}: Install failure: compilation and/or linkage problems." >&5 $as_echo "$as_me: Install failure: compilation and/or linkage problems." >&6;} as_fn_error $? "cannot link projection code" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking GDAL: checking whether PROJ is available fur running:" >&5 $as_echo_n "checking GDAL: checking whether PROJ is available fur running:... " >&6; } ./gdal_proj if test `echo $?` -ne 0 ; then gdal_has_proj=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else gdal_has_proj=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi if test "${gdal_has_proj}" = no; then as_fn_error $? "OGRCoordinateTransformation() does not return a coord.trans: PROJ not available?" "$LINENO" 5 fi rm -fr errors.txt gdal_proj.cpp gdal_proj { $as_echo "$as_me:${as_lineno-$LINENO}: GDAL: ${GDAL_VERSION}" >&5 $as_echo "$as_me: GDAL: ${GDAL_VERSION}" >&6;} # sqlite3 # Check whether --with-sqlite3-lib was given. if test "${with_sqlite3_lib+set}" = set; then : withval=$with_sqlite3_lib; sqlite3_lib_path=$withval fi if test -n "$sqlite3_lib_path" ; then SQLITE3_LIBS="-L${sqlite3_lib_path}" fi # # PROJ # PROJ_CONFIG="pkg-config proj" if `$PROJ_CONFIG --exists` ; then { $as_echo "$as_me:${as_lineno-$LINENO}: pkg-config proj exists, will use it" >&5 $as_echo "$as_me: pkg-config proj exists, will use it" >&6;} proj_config_ok=yes else proj_config_ok=no fi # Check whether --with-proj-include was given. if test "${with_proj_include+set}" = set; then : withval=$with_proj_include; proj_include_path=$withval fi if test -n "$proj_include_path" ; then PROJ_CPPFLAGS="-I${proj_include_path}" else if test "${proj_config_ok}" = yes; then PROJ_INCLUDE_PATH=`${PROJ_CONFIG} --cflags` PROJ_CPPFLAGS="${PROJ_INCLUDE_PATH}" fi fi # honor PKG_xx overrides # for CPPFLAGS we will superfluously double R's flags # since we'll set PKG_CPPFLAGS with this, but that shouldn't hurt # Check whether --with-proj-api was given. if test "${with_proj_api+set}" = set; then : withval=$with_proj_api; proj_api=$withval fi PROJ6="no" PROJH="no" if test "${proj_config_ok}" = yes; then PROJ_VERSION=`${PROJ_CONFIG} --modversion` PROJV1=`echo "${PROJ_VERSION}" | cut -c 1` if test "${PROJV1}" -ge 6; then PROJ6="yes" PROJ_CPPFLAGS="${PROJ_CPPFLAGS} -DHAVE_PROJ_H" if test "${proj_api}" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: using proj_api.h even with PROJ 5/6" >&5 $as_echo "$as_me: using proj_api.h even with PROJ 5/6" >&6;} PROJ_CPPFLAGS="${PROJ_CPPFLAGS} -DACCEPT_USE_OF_DEPRECATED_PROJ_API_H" else { $as_echo "$as_me:${as_lineno-$LINENO}: using proj.h." >&5 $as_echo "$as_me: using proj.h." >&6;} PROJH="yes" fi fi else if test "${PROJH}" = no ; then PROJH=yes for ac_header in proj.h do : ac_fn_c_check_header_mongrel "$LINENO" "proj.h" "ac_cv_header_proj_h" "$ac_includes_default" if test "x$ac_cv_header_proj_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PROJ_H 1 _ACEOF else PROJH=no fi done if test "${PROJH}" = yes; then PROJ6="yes" PROJ_CPPFLAGS="${PROJ_CPPFLAGS} -DHAVE_PROJ_H" fi fi fi CPPFLAGS="${INCPPFLAGS} ${PKG_CPPFLAGS} ${PROJ_CPPFLAGS}" if test "${PROJH}" = no then proj4ok=yes for ac_header in proj_api.h do : ac_fn_c_check_header_mongrel "$LINENO" "proj_api.h" "ac_cv_header_proj_api_h" "$ac_includes_default" if test "x$ac_cv_header_proj_api_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PROJ_API_H 1 _ACEOF else proj4ok=no fi done if test "${proj4ok}" = no; then as_fn_error $? "proj_api.h not found in standard or given locations." "$LINENO" 5 fi fi # dnl ditto for a library path # Check whether --with-proj-lib was given. if test "${with_proj_lib+set}" = set; then : withval=$with_proj_lib; proj_lib_path=$withval fi if test -n "$proj_lib_path" ; then PROJ_LIBS="-L${proj_lib_path} ${INPKG_LIBS} -lproj" else if test "${proj_config_ok}" = yes; then if test `uname` = "Darwin"; then PROJ_LIB_PATH=`${PROJ_CONFIG} --libs --static` else PROJ_LIB_PATH=`${PROJ_CONFIG} --libs` fi PROJ_LIBS="${PROJ_LIB_PATH} ${INPKG_LIBS}" proj_version=`${PROJ_CONFIG} --modversion` { $as_echo "$as_me:${as_lineno-$LINENO}: PROJ: ${proj_version}" >&5 $as_echo "$as_me: PROJ: ${proj_version}" >&6;} else PROJ_LIBS="${PKG_LIBS} -lproj" fi fi LIBS="${PROJ_LIBS} ${INLIBS} ${PKG_LIBS}" if test "${PROJH}" = no; then proj4ok=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pj_init_plus in -lproj" >&5 $as_echo_n "checking for pj_init_plus in -lproj... " >&6; } if ${ac_cv_lib_proj_pj_init_plus+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lproj $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pj_init_plus (); int main () { return pj_init_plus (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_proj_pj_init_plus=yes else ac_cv_lib_proj_pj_init_plus=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_proj_pj_init_plus" >&5 $as_echo "$ac_cv_lib_proj_pj_init_plus" >&6; } if test "x$ac_cv_lib_proj_pj_init_plus" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPROJ 1 _ACEOF LIBS="-lproj $LIBS" else proj4ok=no fi if test "${proj4ok}" = no; then as_fn_error $? "libproj not found in standard or given locations." "$LINENO" 5 fi cat > proj_conf_test.c <<_EOCONF #include #include #include int main() { printf("%d\n", PJ_VERSION); exit(0); } _EOCONF else cat > proj_conf_test.cpp <<_EOCONF #include #include #include int main() { proj_context_create(); exit(0); } _EOCONF #AC_CHECK_LIB(proj,proj_context_create,,proj6ok=no) { $as_echo "$as_me:${as_lineno-$LINENO}: checking PROJ: checking whether PROJ and sqlite3 are available for linking:" >&5 $as_echo_n "checking PROJ: checking whether PROJ and sqlite3 are available for linking:... " >&6; } ${CXX} ${CPPFLAGS} -o proj_conf_test proj_conf_test.cpp ${LIBS} $SQLITE3_LIBS -lsqlite3 2> errors.txt if test `echo $?` -ne 0 ; then proj6ok=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else proj6ok=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi if test "${proj6ok}" = no; then as_fn_error $? "libproj or sqlite3 not found in standard or given locations." "$LINENO" 5 fi cat > proj_conf_test.c <<_EOCONF #include #include #include int main() { printf("%d.%d.%d\n", PROJ_VERSION_MAJOR, PROJ_VERSION_MINOR, PROJ_VERSION_PATCH); exit(0); } _EOCONF fi #AC_MSG_NOTICE([PKG_LIBS: ${PKG_LIBS}]) ${CC} ${CFLAGS} ${CPPFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS} proj_version=`./proj_conf_test` # Check whether --with-proj-share was given. if test "${with_proj_share+set}" = set; then : withval=$with_proj_share; proj_share_path=$withval fi if test -n "$proj_share_path" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: PROJ_LIB: ${proj_share_path}" >&5 $as_echo "$as_me: PROJ_LIB: ${proj_share_path}" >&6;} fi if test ${PROJ6} = "no"; then cat > proj_conf_test.c <<_EOCONF #include #include #if PJ_VERSION <= 480 FILE *pj_open_lib(projCtx, const char *, const char *); #endif int main() { #if PJ_VERSION <= 480 FILE *fp; #else PAFile fp; #endif projCtx ctx; ctx = pj_get_default_ctx(); fp = pj_open_lib(ctx, "epsg", "rb"); if (fp == NULL) exit(1); #if PJ_VERSION <= 480 fclose(fp); #else pj_ctx_fclose(ctx, fp); #endif exit(0); } _EOCONF ${CC} ${CFLAGS} ${CPPFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS} if test -n "$proj_share_path" ; then PROJ_LIB="${proj_share_path}" ./proj_conf_test proj_share=`echo $?` else ./proj_conf_test proj_share=`echo $?` fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking PROJ: epsg found and readable" >&5 $as_echo_n "checking PROJ: epsg found and readable... " >&6; } if test ${proj_share} -eq 1 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } STOP="stop" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi rm -f proj_conf_test.c proj_conf_test if test "$STOP" = "stop" ; then echo "Error: proj/epsg not found" echo "Either install missing proj support files, for example" echo "the proj-nad and proj-epsg RPMs on systems using RPMs," echo "or if installed but not autodetected, set PROJ_LIB to the" echo "correct path, and if need be use the --with-proj-share=" echo "configure argument." exit 1 fi else # proj >= 6 if test "${PROJH}" = no; then cat > proj_conf_test.c <<_EOCONF #include #include int main() { PAFile fp; projCtx ctx; ctx = pj_get_default_ctx(); fp = pj_open_lib(ctx, "proj.db", "rb"); if (fp == NULL) exit(1); pj_ctx_fclose(ctx, fp); exit(0); } _EOCONF ${CC} ${CFLAGS} ${CPPFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS} if test -n "$proj_share_path" ; then PROJ_LIB="${proj_share_path}" ./proj_conf_test proj_share=`echo $?` else ./proj_conf_test proj_share=`echo $?` fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking PROJ: proj.db found and readable" >&5 $as_echo_n "checking PROJ: proj.db found and readable... " >&6; } if test ${proj_share} -eq 1 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } STOP="stop" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi rm -f proj_conf_test.c proj_conf_test if test "$STOP" = "stop" ; then echo "Error: proj/proj.db not found" echo "Either install missing proj support files, set PROJ_LIB to the" echo "correct path, and if need be use the --with-proj-share=" echo "configure argument." exit 1 fi cat > proj_conf_test.c <<_EOCONF #include #include #if PJ_VERSION <= 480 FILE *pj_open_lib(projCtx, const char *, const char *); #endif int main() { #if PJ_VERSION <= 480 FILE *fp; #else PAFile fp; #endif projCtx ctx; ctx = pj_get_default_ctx(); fp = pj_open_lib(ctx, "conus", "rb"); if (fp == NULL) exit(1); #if PJ_VERSION <= 480 fclose(fp); #else pj_ctx_fclose(ctx, fp); #endif exit(0); } _EOCONF ${CC} ${CFLAGS} ${CPPFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS} if test -n "$proj_share_path" ; then PROJ_LIB="${proj_share_path}" ./proj_conf_test proj_share=`echo $?` else ./proj_conf_test proj_share=`echo $?` fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking PROJ: conus found and readable" >&5 $as_echo_n "checking PROJ: conus found and readable... " >&6; } if test ${proj_share} -eq 1 ; then WARN="warn" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi rm -f proj_conf_test.c proj_conf_test if test "$WARN" = "warn" ; then echo "Note: proj/conus not found" echo "No support available in PROJ4 for NAD grid datum transformations" echo "If required, consider re-installing from source with the contents" echo "of proj-datumgrid-1..zip from http://download.osgeo.org/proj/ in nad/." fi fi # PROJH = no fi # proj >= 6 # # GEOS: # GEOS_CONFIG="geos-config" GEOS_CONFIG_SET="no" # Check whether --with-geos-config was given. if test "${with_geos_config+set}" = set; then : withval=$with_geos_config; geos_config=$withval fi if test -n "$geos_config" ; then GEOS_CONFIG_SET="yes" GEOS_CONFIG="${geos_config}" { $as_echo "$as_me:${as_lineno-$LINENO}: geos-config set to $GEOS_CONFIG" >&5 $as_echo "$as_me: geos-config set to $GEOS_CONFIG" >&6;} fi if test "$GEOS_CONFIG_SET" = "no" ; then # Extract the first word of ""$GEOS_CONFIG"", so it can be a program name with args. set dummy "$GEOS_CONFIG"; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GEOS_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $GEOS_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_GEOS_CONFIG="$GEOS_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GEOS_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_GEOS_CONFIG" && ac_cv_path_GEOS_CONFIG=""no"" ;; esac fi GEOS_CONFIG=$ac_cv_path_GEOS_CONFIG if test -n "$GEOS_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GEOS_CONFIG" >&5 $as_echo "$GEOS_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$GEOS_CONFIG" = "no" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "geos-config not found or not executable." "$LINENO" 5 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking geos-config exists" >&5 $as_echo_n "checking geos-config exists... " >&6; } if test -r "${GEOS_CONFIG}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "geos-config not found - configure argument error." "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking geos-config executable" >&5 $as_echo_n "checking geos-config executable... " >&6; } if test -x "${GEOS_CONFIG}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "geos-config not executable." "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking geos-config usability" >&5 $as_echo_n "checking geos-config usability... " >&6; } if test `${GEOS_CONFIG} --version` then GEOS_CLIBS="`${GEOS_CONFIG} --clibs`" #GEOS_DEP_CLIBS=`geos-config --static-clibs` -- this gives -m instead of -lm, which breaks clang # fixed in 3.7.0 at https://github.com/libgeos/libgeos/pull/73#issuecomment-262208677 GEOS_DEP_CLIBS=`${GEOS_CONFIG} --static-clibs | sed 's/-m/-lm/g'` GEOS_CPPFLAGS=`${GEOS_CONFIG} --cflags` { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "${GEOS_CONFIG} not usable" "$LINENO" 5 fi GEOS_VERSION=`${GEOS_CONFIG} --version` { $as_echo "$as_me:${as_lineno-$LINENO}: GEOS: ${GEOS_VERSION}" >&5 $as_echo "$as_me: GEOS: ${GEOS_VERSION}" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking GEOS version >= 3.4.0" >&5 $as_echo_n "checking GEOS version >= 3.4.0... " >&6; } # GDAL 2.0.1 requires GEOS 3.1.0 GEOS_VER_DOT=`echo $GEOS_VERSION | tr -d ".[:alpha:]"` if test ${GEOS_VER_DOT} -lt 340 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "upgrade GEOS to 3.4.0 or later" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi PKG_CPPFLAGS="${INPKG_CPPFLAGS} ${PROJ_CPPFLAGS} ${GDAL_CPPFLAGS} ${GEOS_CPPFLAGS}" PKG_LIBS="${INPKG_LIBS} ${GDAL_LIBS}" if test "${NEED_DEPS}" = yes; then PKG_LIBS="${PKG_LIBS} ${GDAL_DEP_LIBS}" fi # honor PKG_xx overrides # for CPPFLAGS we will superfluously double R's flags # since we'll set PKG_CPPFLAGS with this, but that shouldn't hurt CPPFLAGS="${CPPFLAGS} ${PKG_CPPFLAGS}" LIBS="${LIBS} ${PKG_LIBS}" geosok=yes for ac_header in geos_c.h do : ac_fn_c_check_header_mongrel "$LINENO" "geos_c.h" "ac_cv_header_geos_c_h" "$ac_includes_default" if test "x$ac_cv_header_geos_c_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GEOS_C_H 1 _ACEOF else geosok=no fi done if test "${geosok}" = no; then as_fn_error $? "geos_c.h not found in given locations." "$LINENO" 5 fi cat > geos_test.cpp <<_EOCONF #include #ifdef __cplusplus extern "C" { #endif static void __errorHandler(const char *fmt, ...) { return; } static void __warningHandler(const char *fmt, ...) { return; } int main() { GEOSContextHandle_t r = initGEOS_r((GEOSMessageHandler) __warningHandler, (GEOSMessageHandler) __errorHandler); finishGEOS_r(r); } #ifdef __cplusplus } #endif _EOCONF #echo "${CXX} ${CPPFLAGS} -o geos_test geos_test.cpp ${LIBS}" { $as_echo "$as_me:${as_lineno-$LINENO}: checking geos: linking with ${GEOS_CLIBS}" >&5 $as_echo_n "checking geos: linking with ${GEOS_CLIBS}... " >&6; } ${CXX} ${CPPFLAGS} -o geos_test geos_test.cpp ${GEOS_CLIBS} 2> errors.txt if test `echo $?` -ne 0 ; then geosok=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else PKG_LIBS="${PKG_LIBS} ${GEOS_CLIBS}" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi if test "${geosok}" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking geos: linking with ${GEOS_DEP_CLIBS}" >&5 $as_echo_n "checking geos: linking with ${GEOS_DEP_CLIBS}... " >&6; } ${CXX} ${CPPFLAGS} -o geos_test geos_test.cpp ${GEOS_DEP_CLIBS} 2> errors.txt if test `echo $?` -ne 0 ; then geosok=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } cat errors.txt { $as_echo "$as_me:${as_lineno-$LINENO}: Install failure: compilation and/or linkage problems." >&5 $as_echo "$as_me: Install failure: compilation and/or linkage problems." >&6;} as_fn_error $? "initGEOS_r not found in libgeos_c." "$LINENO" 5 else PKG_LIBS="${PKG_LIBS} ${GEOS_DEP_CLIBS}" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi rm -f geos_test errors.txt geos_test.cpp # # add PROJ_LIBS # PKG_LIBS="${PROJ_LIBS} ${PKG_LIBS}" # # concluding substitution # { $as_echo "$as_me:${as_lineno-$LINENO}: Package CPP flags: ${PKG_CPPFLAGS}" >&5 $as_echo "$as_me: Package CPP flags: ${PKG_CPPFLAGS}" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: Package LIBS: ${PKG_LIBS}" >&5 $as_echo "$as_me: Package LIBS: ${PKG_LIBS}" >&6;} ac_config_files="$ac_config_files src/Makevars" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "src/Makevars") CONFIG_FILES="$CONFIG_FILES src/Makevars" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi terra/R/0000755000175000017500000000000014201035747011725 5ustar nileshnileshterra/R/match.R0000644000175000017500000000277314201035747013155 0ustar nileshnilesh# Author: Robert J. Hijmans # License GPL v3 getCatIDs <- function(x, table, sender="%in%") { if (!is.factor(x)) { error(sender, "Can only match character values if x is categorical") } if (nlyr(x) != 1) { error(sender, "matching with character values is only supported for single layer SpatRaster") } d <- cats(x)[[1]] levs <- levels(x)[[1]] m <- na.omit(match(table, levs)) d[m,1] } setMethod("match", signature(x="SpatRaster"), function(x, table, nomatch=NA, incomparables=NULL) { table <- unique(table) if (is.character(table)) { table <- getCatIDs(x, table, sender="match") if (length(table) == 0) { return(as.logical(x*0)) } } app(x, function(i) match(i, table, nomatch, incomparables)) } ) setMethod("%in%", signature(x="SpatRaster"), function(x, table) { table <- unique(table) if (is.character(table)) { table <- getCatIDs(x, table) if (length(table) == 0) { return(as.logical(x*0)) } } opt <- spatOptions("", FALSE, list()) x@ptr <- x@ptr$is_in(table, opt) messages(x, "%in%") } ) #setMethod("%in%", signature(x="SpatRaster", table="ANY"), # function(x, table) { # out <- rast(x) # readStart(x) # on.exit(readStop(x)) # nc <- ncol(out) # b <- writeStart(out, filename="", overwrite=FALSE, wopt=list()) # for (i in 1:b$n) { # v <- readValues(x, b$row[i], b$nrows[i], 1, nc, TRUE) # v <- v %in% table # writeValues(out, v, b$row[i], b$nrows[i]) # } # writeStop(out) # } #) terra/R/geom.R0000644000175000017500000002171514201035747013005 0ustar nileshnilesh roundtrip <- function(x, coll=FALSE) { if (coll) { p <- methods::new("SpatVectorCollection") p@ptr <- x@ptr$bienvenue() return(p) } else { x@ptr <- x@ptr$allerretour() return(x) } } get_invalid_coords <- function(x) { x <- x[!x[,1], ] if (nrow(x) > 0) { id <- as.integer(rownames(x)) txt <- x[,2] txt <- gsub("Ring Self-intersection\\[", "", txt) txt <- gsub("Self-intersection\\[", "", txt) txt <- gsub("Too few points in geometry component\\[", "", txt) txt <- unlist(strsplit(gsub("]", "", txt), " ")) txt <- matrix(as.numeric(txt), ncol=2, byrow=TRUE) v <- vect(txt) values(v) <- data.frame(id=id, msg=x[,2]) v } else { vect() } } setMethod("is.valid", signature(x="SpatVector"), function(x, messages=FALSE, as.points=FALSE) { if (as.points) messages = TRUE if (messages) { r <- x@ptr$geos_isvalid_msg() d <- data.frame(matrix(r, ncol=2, byrow=TRUE)) d[,1] = d[,1] == "\001" colnames(d) <- c("valid", "reason") if (as.points) { p <- try(get_invalid_coords(d), silent=TRUE) if (inherits(p, "try-error")) { warn("is.valid", "as.points failed, returning matrix") return(d) } else { return(p) } } d } else { x@ptr$geos_isvalid() } } ) setMethod("makeValid", signature(x="SpatVector"), function(x) { x@ptr <- x@ptr$make_valid2() messages(x) } ) setMethod("na.omit", signature("SpatVector"), function(object, field=NA, geom=FALSE) { if (geom) { g <- geom(object) g <- g[is.na(g[,"x"]) | is.na(g[,"y"]), 1] if (length(g) > 0) { object <- object[-g, ] } } if (!is.na(field)) { v <- values(object) if (field != "") { v <- v[, field, drop=FALSE] } i <- apply(v, 1, function(i) any(is.na(i))) if (any(i)) { object <- object[!i, ] } } object } ) setMethod("deepcopy", signature("SpatVector"), function(x) { x@ptr <- x@ptr$deepcopy() x } ) as.list.svc <- function(x) { v <- vect() lapply(1:x$size(), function(i) { v@ptr <- x$get(i-1) v }) } setMethod("split", signature(x="SpatVector"), function(x, f) { if (length(f) > 1) { x <- copy(x) x$f <- f f <- "f" } x <- messages(x@ptr$split(f), "split") as.list.svc(x) } ) setMethod("cover", signature(x="SpatVector", y="SpatVector"), function(x, y, identity=FALSE) { x@ptr <- x@ptr$cover(y@ptr, identity[1]) messages(x, "cover") } ) setMethod("symdif", signature(x="SpatVector", y="SpatVector"), function(x, y) { x@ptr <- x@ptr$symdif(y@ptr) messages(x, "symdif") } ) setMethod("erase", signature(x="SpatVector", y="SpatVector"), function(x, y) { x@ptr <- x@ptr$erase(y@ptr) messages(x, "erase") } ) setMethod("erase", signature(x="SpatVector", y="missing"), function(x) { x@ptr <- x@ptr$erase_self() messages(x, "erase") } ) setMethod("erase", signature(x="SpatVector", y="SpatExtent"), function(x, y) { y <- as.polygons(y) x@ptr <- x@ptr$erase(y@ptr) messages(x, "erase") } ) setMethod("gaps", signature(x="SpatVector"), function(x) { x@ptr <- x@ptr$gaps() messages(x, "gaps") } ) setMethod("union", signature(x="SpatVector", y="missing"), function(x, y) { x@ptr <- x@ptr$union_self() messages(x, "union") } ) setMethod("union", signature(x="SpatVector", y="SpatVector"), function(x, y) { x@ptr <- x@ptr$union(y@ptr) messages(x, "union") } ) setMethod("union", signature(x="SpatVector", y="SpatExtent"), function(x, y) { y <- as.vector(y) x@ptr <- x@ptr$union(y@ptr) messages(x, "union") } ) setMethod("union", signature(x="SpatExtent", y="SpatExtent"), function(x, y) { x + y } ) setMethod("intersect", signature(x="SpatVector", y="SpatVector"), function(x, y) { x@ptr <- x@ptr$intersect(y@ptr) messages(x, "intersect") } ) setMethod("intersect", signature(x="SpatExtent", y="SpatExtent"), function(x, y) { x@ptr = x@ptr$intersect(y@ptr) if (!x@ptr$valid) { return(NULL) } x } ) setMethod("intersect", signature(x="SpatVector", y="SpatExtent"), function(x, y) { x@ptr <- x@ptr$crop_ext(y@ptr) x } ) setMethod("intersect", signature(x="SpatExtent", y="SpatVector"), function(x, y) { y <- ext(y) x * y } ) setMethod("mask", signature(x="SpatVector", mask="SpatVector"), function(x, mask, inverse=FALSE) { x@ptr <- x@ptr$mask(mask@ptr, inverse) messages(x, "intersect") } ) #setMethod("intersect", signature(x="SpatRaster", y="SpatRaster"), # function(x, y) { # a <- crop(x, y) # b <- crop(y, x) # c(a, b) # } #) setMethod("buffer", signature(x="SpatVector"), function(x, width, quadsegs=10) { x@ptr <- x@ptr$buffer(width, quadsegs) messages(x, "buffer") } ) setMethod("crop", signature(x="SpatVector", y="ANY"), function(x, y) { if (inherits(y, "SpatVector")) { if (length(y) > 1) { y <- aggregate(y) } x@ptr <- x@ptr$crop_vct(y@ptr) } else { if (!inherits(y, "SpatExtent")) { y <- try(ext(y), silent=TRUE) if (inherits(y, "try-error")) { stop("y does not have a SpatExtent") } } x@ptr <- x@ptr$crop_ext(y@ptr) } messages(x, "crop") } ) setMethod("convHull", signature(x="SpatVector"), function(x, by="") { x@ptr <- x@ptr$hull("convex", by[1]) messages(x, "convHull") } ) setMethod("minRect", signature(x="SpatVector"), function(x, by="") { x@ptr <- x@ptr$hull("minrot", by[1]) messages(x, "minRect") } ) setMethod("disagg", signature(x="SpatVector"), function(x) { x@ptr <- x@ptr$disaggregate() messages(x, "disagg") } ) setMethod("flip", signature(x="SpatVector"), function(x, direction="vertical") { d <- match.arg(direction, c("vertical", "horizontal")) x@ptr <- x@ptr$flip(d == "vertical") messages(x, "flip") } ) setMethod("spin", signature(x="SpatVector"), function(x, angle, x0, y0) { e <- as.vector(ext(x)) if (missing(x0)) { x0 <- mean(e[1:2]) } if (missing(y0)) { y0 <- mean(e[3:4]) } angle <- angle[1] stopifnot(is.numeric(angle) && !is.nan(angle)) x@ptr <- x@ptr$rotate(angle, x0[1], y0[1]) messages(x, "spin") } ) setMethod("delauny", signature(x="SpatVector"), function(x, tolerance=0, as.lines=FALSE) { x@ptr <- x@ptr$delauny(tolerance, as.lines) messages(x, "delauny") } ) voronoi_deldir <- function(x, bnd=NULL, eps=1e-09, ...){ xy <- crds(x) dat <- values(x) if (nrow(dat > 0)) { dups <- duplicated(xy) if (any(dups)) { xy <- xy[!dups, ,drop=FALSE] dat <- dat[!dups, ,drop=FALSE] } } else { xy <- stats::na.omit(xy[, 1:2]) xy <- unique(xy) } e <- bnd if (!is.null(e)) { e <- as.vector(ext(bnd)) } dd <- deldir::deldir(xy[,1], xy[,2], rw=e, eps=eps, suppressMsge=TRUE) g <- lapply(deldir::tile.list(dd), function(i) cbind(i$ptNum, 1, i$x, i$y)) g <- do.call(rbind, g) g <- vect(g, "polygons", crs=crs(x)) if (nrow(g) == nrow(dat)) { values(g) <- dat } else { values(g) <- data.frame(id=dd$ind.orig) } g } setMethod("voronoi", signature(x="SpatVector"), function(x, bnd=NULL, tolerance=0, as.lines=FALSE, deldir=FALSE) { if (geomtype(x) != "points") { x <- as.points(x) } if (deldir) { voronoi_deldir(x, bnd, tolerance=tolerance) } else { if (is.null(bnd)) { bnd <- vect() } else { bnd <- as.polygons(ext(bnd)) } x@ptr <- x@ptr$voronoi(bnd@ptr, tolerance, as.lines) messages(x, "voronoi") } } ) setMethod("width", signature(x="SpatVector"), function(x, as.lines=FALSE) { x@ptr <- x@ptr$width() x <- messages(x, "width") if (!as.lines) { x <- perim(x) } x } ) setMethod("clearance", signature(x="SpatVector"), function(x, as.lines=FALSE) { x@ptr <- x@ptr$clearance() x <- messages(x, "clearance") if (!as.lines) { x <- perim(x) } x } ) setMethod("mergeLines", signature(x="SpatVector"), function(x) { x@ptr <- x@ptr$line_merge() messages(x, "line_merge") } ) setMethod("makeNodes", signature(x="SpatVector"), function(x) { x@ptr <- x@ptr$make_nodes() messages(x, "makeNodes") } ) setMethod("removeDupNodes", signature(x="SpatVector"), function(x, digits=-1) { x@ptr <- x@ptr$remove_duplicate_nodes(digits) messages(x, "removeDupNodes") } ) setMethod("simplifyGeom", signature(x="SpatVector"), function(x, tolerance=0.1) { preserveTopology <- TRUE x@ptr <- x@ptr$simplify(tolerance, preserveTopology) messages(x, "simplifyGeom") } ) setMethod("sharedPaths", signature(x="SpatVector"), function(x) { x@ptr <- x@ptr$shared_paths() messages(x, "sharedPaths") } ) setMethod("snap", signature(x="SpatVector"), function(x, y=NULL, tolerance) { if (is.null(y)) { x@ptr <- x@ptr$snap(tolerance) } else { x@ptr <- x@ptr$snapto(y@ptr, tolerance) } messages(x, "snap") } ) terra/R/tiles.R0000644000175000017500000000231214201035747013166 0ustar nileshnilesh setMethod("makeTiles", signature(x="SpatRaster"), function(x, y, filename="tile_.tif", extend=FALSE, na.rm=FALSE, ...) { filename = trimws(filename[1]) filename <- filename[!is.na(filename)] if (filename == "") error("makeTiles", "filename cannot be empty") if (!inherits(y, "SpatRaster")) error("makeTiles", "y must be a SpatRaster") opt <- spatOptions(filename="", ...) ff <- x@ptr$make_tiles(y@ptr, extend[1], na.rm[1], filename, opt) messages(x) return (ff) } ) # if (!hasValues(x)) error("makeTiles", "x has no values") # y <- rast(y)[[1]] # if (expand) y <- expand(y, ext(x), snap="out") # y <- crop(rast(y)[[1]], x, snap="out") # d <- 1:ncell(y) # if (length(filename) == 0) error("tiler", "no valid filename supplied") # e <- paste0(".", tools::file_ext(filename)) # f <- tools::file_path_sans_ext(filename) # ff <- paste0(f, d, e) # for (i in d) { # crop(x, y[i,drop=FALSE], filename=ff[i], ...) # } # ff[file.exists(ff)] # } #) setMethod("vrt", signature(x="character"), function(x, filename="", overwrite=FALSE) { opt <- spatOptions(filename, overwrite=overwrite) r <- rast() r@ptr <- r@ptr$make_vrt(x, opt) messages(r) } ) terra/R/geocolors.R0000644000175000017500000000061714201035747014050 0ustar nileshnilesh.geocolors <- function(name, ...) { if (name == "aspect") { #0% black, 50% white, 100% black pal <- grDevices::colorRampPalette(c("black", "white", "black"), ...) cols <- cbind(1:360, pal(360)) } else if (name == "aspectclr") { pal <- grDevices::colorRampPalette(c("yellow", "green", "cyan", "red", "yellow"), ...) cols <- cbind(1:360, pal(360)) cols[1,2] <- "#FFFFFF" } } terra/R/layerCor.R0000644000175000017500000000611114201035747013627 0ustar nileshnilesh# Robert Hijmans # Date : Nov 2021 # Version 1.0 # Licence GPL v3 # Computation of the weighted covariance and (optionally) weighted means of bands in an Raster. # based on code for "raster" by Jonathan Greenberg and Robert Hijmans partly based on code by Mort Canty if (!isGeneric("layerCor")) {setGeneric("layerCor", function(x, ...) standardGeneric("layerCor"))} setMethod("layerCor", signature(x="SpatRaster"), function(x, fun, w, asSample=TRUE, na.rm=FALSE, maxcell=Inf, ...) { stopifnot(is.logical(asSample) & !is.na(asSample)) nl <- nlyr(x) n <- ncell(x) mat <- matrix(NA, nrow=nl, ncol=nl) colnames(mat) <- rownames(mat) <- names(x) if (inherits(fun, "character")) { fun <- tolower(fun) stopifnot(fun %in% c("cov", "weighted.cov", "pearson")) } else { FUN <- fun fun <- "" } if (fun == "weighted.cov") { if (missing(w)) { stop("to compute weighted covariance a weights layer should be provided") } stopifnot( nlyr(w) == 1 ) if (na.rm) { # a cell is set to NA if it is NA in any layer. That is not ideal, but easier and quicker nas <- sum(x) * w x <- mask(x, nas) w <- mask(w, nas) } sumw <- unlist(global(w, fun="sum", na.rm=na.rm) ) means <- unlist(global(x * w, fun="sum", na.rm=na.rm)) / sumw sumw <- sumw - asSample x <- (x - means) * sqrt(w) for(i in 1:nl) { for(j in i:nl) { r <- x[[i]] * x[[j]] v <- unlist(global(r, fun="sum", na.rm=na.rm)) / sumw mat[j,i] <- mat[i,j] <- v } } names(means) <- names(x) cov.w <- list(mat, means) names(cov.w) <- c("weighted_covariance", "weighted_mean") return(cov.w) } else if (fun == "cov") { means <- unlist(global(x, fun="mean", na.rm=na.rm) ) x <- (x - means) for(i in 1:nl) { for(j in i:nl) { r <- x[[i]] * x[[j]] if (na.rm) { v <- unlist(global(r, fun="sum", na.rm=na.rm)) / (n - unlist(global(is.na(r), fun="sum")) - asSample) } else { v <- unlist(global(r, fun="sum", na.rm=na.rm)) / (n - asSample) } mat[j,i] <- mat[i,j] <- v } } names(means) <- names(x) covar <- list(mat, means) names(covar) <- c("covariance", "mean") return(covar) } else if (fun == "pearson") { means <- unlist(global(x, fun="mean", na.rm=na.rm) ) sds <- unlist(global(x, fun="sd", na.rm=na.rm) ) x <- (x - means) for(i in 1:nl) { for(j in i:nl) { r <- x[[i]] * x[[j]] v <- unlist(global(r, fun="sum", na.rm=na.rm)) if (na.rm) { nas <- unlist(global(is.na(r), fun="sum")) v <- v / ((n - nas - asSample) * sds[i] * sds[j]) } else { v <- v / ((n - asSample) * sds[i] * sds[j]) } mat[j,i] <- mat[i,j] <- v } } names(means) <- names(x) covar <- list(mat, means) names(covar) <- c("pearson", "mean") return(covar) } else { v <- spatSample(x, size=maxcell, "regular", na.rm=na.rm) for(i in 1:nl) { for(j in i:nl) { mat[j,i] <- mat[i,j] <- FUN(v[,i], v[,j]) } } mat } } ) terra/R/spatDF.R0000644000175000017500000000161614201035747013235 0ustar nileshnilesh .makeSpatDF <- function(d) { x <- methods::new("Rcpp_SpatDataFrame") cls <- sapply(d, class) nms <- colnames(d) for (i in 1:length(cls)) { if (cls[i] == "factor") { x$add_column_string(as.character(d[[i]]), nms[i]) } else if (cls[i] == "character") { x$add_column_string(d[[i]], nms[i]) } else if (cls[i] == "integer") { v <- d[[i]] # min long v[is.na(v)] <- -2147483648 x$add_column_long(v, nms[i]) } else { v <- as.numeric(d[[i]]) x$add_column_double(v, nms[i]) } } x } .getSpatDF <- function(x, check.names = FALSE, stringsAsFactors=FALSE, ...) { d <- data.frame(x$values(), check.names=check.names, stringsAsFactors=stringsAsFactors, ...) d[d=="NA"] <- NA s <- which(sapply(d, class) == "character") for (i in s) Encoding(d[[i]]) <- "UTF-8" ints <- which(x$itype == 1) for (i in ints) d[[i]] <- as.integer(d[[i]]) d } terra/R/lines.R0000644000175000017500000000545214201035747013170 0ustar nileshnilesh setMethod("lines", signature(x="SpatRaster"), function(x, mx=10000, ...) { if(prod(dim(x)) > mx) { error("lines", "too many lines (you can increase the value of mx or use as.polygons)") } v <- as.polygons(x, dissolve=FALSE, values=FALSE) lines(v, ...) } ) setMethod("lines", signature(x="SpatVector"), function(x, y=NULL, col, lwd=1, lty=1, arrows=FALSE, alpha=1, ...) { if (nrow(x) == 0) return(invisible(NULL)) gtype <- geomtype(x) if (missing(col)) col <- "black" if (!is.null(y)) { stopifnot(inherits(y, "SpatVector")) ytype <- geomtype(y) if ((ytype != "points") || (gtype != "points")) { error("lines", "when supplying two SpatVectors, both must have point geometry") } stopifnot(nrow(x) == nrow(y)) p1 <- geom(x)[, c("x", "y"), drop=FALSE] p2 <- geom(y)[, c("x", "y"), drop=FALSE] if (arrows) { arrows(p1[,1], p1[,2], p2[,1], p2[,2], col=col, lwd=lwd, lty=lty, ...) } else { a <- as.vector(t(cbind(p1[,1], p2[,1], NA))) b <- as.vector(t(cbind(p1[,2], p2[,2], NA))) lines(cbind(a, b), col=col, lwd=lwd, lty=lty, alpha=alpha, ...) } } else if (grepl("points", gtype)) { points(x, col=col, type="l", lwd=lwd, lty=lty, alpha=alpha, ...) } else { n <- length(x) col <- .getCols(n, col, alpha) lwd <- rep_len(lwd, n) lty <- rep_len(lty, n) g <- geom(x, df=TRUE) g <- split(g, g[,1]) if (gtype == "polygons") { g <- lapply(g, function(x) split(x, x[,c(2,5)])) } else { g <- lapply(g, function(x) split(x, x[,2])) } #p <- sapply(g, function(x) lapply(x, function(y) graphics::lines(y[,3:4], ...))) for (i in 1:length(g)) { x <- g[[i]] for (j in 1:length(x)) { lines(x[[j]][,3:4], col=col[i], lwd=lwd[i], lty=lty[i], ...) } } } } ) setMethod("points", signature(x="SpatVector"), function(x, col, cex=1, pch=20, alpha=1, ...) { if (nrow(x) == 0) return(invisible(NULL)) if (missing(col)) col <- "black" n <- length(x) col <- .getCols(n, col, alpha) cex <- rep_len(cex, n) pch <- rep_len(pch, n) g <- geom(x, df=TRUE) if (any(table(g$id) > 1)) { g <- split(g, g[,1]) for (i in 1:n) { graphics::points(g[[i]][,3:4], col=col[i], pch=pch[i], cex=cex[i], ...) } } else { graphics::points(g[,3:4], col=col, pch=pch, cex=cex,...) } } ) setMethod("polys", signature(x="SpatVector"), function(x, col, border="black", lwd=1, lty=1, alpha=1, ...) { if (nrow(x) == 0) return(invisible(NULL)) gtype <- geomtype(x) if (gtype != "polygons") { error("polys", "expecting polygons") } if (missing(col)) { col <- NULL } cols <- .getCols(length(x), col, alpha) out <- list(main_cols=cols) out$leg$border <- border .plotPolygons(x, out, lwd=lwd, lty=lty, ...) } ) terra/R/options.R0000644000175000017500000000723614201035747013553 0ustar nileshnilesh .terra_environment <- new.env(parent=emptyenv()) .create_options <- function() { opt <- methods::new("SpatOptions") opt@ptr <- SpatOptions$new() # check=T does not exist in ancient R tmpdir <- try(tempdir(check = TRUE), silent=TRUE) opt@ptr$tempdir <- normalizePath(tempdir(), winslash="/") .terra_environment$options <- opt } .options_names <- function() { c("progress", "tempdir", "memfrac", "memmax", "datatype", "filetype", "filenames", "overwrite", "todisk", "names", "verbose", "NAflag", "statistics", "steps", "ncopies", "tolerance", "pid") #, "append") } .setOptions <- function(x, wopt) { nms <- names(wopt) g <- which(nms == "gdal") if (length(g) > 0) { gopt <- unlist(wopt[g]) wopt <- wopt[-g] nms <- nms[-g] i <- grep("=", gopt) gopt <- gopt[i] gopt <- gsub(" ", "", gopt) x$gdal_options <- gopt } s <- nms %in% .options_names() if (any(!s)) { bad <- paste(nms[!s], collapse=",") error("write", "unknown option(s): ", bad) } if (any(s)) { nms <- nms[s] wopt <- wopt[s] i <- which(nms == "names") if (length(i) > 0) { namevs <- trimws(unlist(strsplit(as.character(wopt[[i]]), ","))) x[["names"]] <- namevs wopt <- wopt[-i] nms <- nms[-i] } for (i in seq_along(nms)) { x[[nms[i]]] <- wopt[[i]] } if ("datatype" %in% nms) { x$datatype_set = TRUE; } } x } defaultOptions <- function() { ## work around onLoad problem if (is.null(.terra_environment$options)) .create_options() .terra_environment$options@ptr$deepcopy() } spatOptions <- function(filename="", overwrite=FALSE, ..., wopt=NULL) { wopt <- c(list(...), wopt) ## work around onLoad problem if (is.null(.terra_environment$options)) .create_options() opt <- .terra_environment$options@ptr$deepcopy() opt$pid <- Sys.getpid() filename <- .fullFilename(filename, mustExist=FALSE) if (!is.null(unlist(wopt))) { wopt$filenames <- filename wopt$overwrite <- overwrite[1] opt <- .setOptions(opt, wopt) } else { opt$filenames <- filename opt$overwrite <- overwrite[1] } #messages(opt) #opt$todisk <- TRUE opt } #..getOptions <- function() { # spatOptions("", TRUE, list()) #} #..showOptions <- function(opt) { # cat("Options for package 'terra'\n") # cat("memfrac :" , opt$memfrac, "\n") # cat("tempdir :" , opt$tempdir, "\n") # cat("datatype :" , opt$def_datatype, "\n") # cat("filetype :" , opt$def_filetype, "\n") # cat("progress :" , opt$progress, "\n") # cat("verbose :" , opt$verbose, "\n") # if (opt$todisk) { # cat("todisk :" , opt$todisk, "\n") # } #} .showOptions <- function(opt) { nms <- c("memfrac", "tempdir", "datatype", "progress", "todisk", "verbose", "tolerance") for (n in nms) { v <- eval(parse(text=paste0("opt$", n))) cat(paste0(substr(paste(n, " "), 1, 10), ": ", v, "\n")) } if (opt$memmax > 0) { cat(paste0("memmax : ", 8 * opt$memmax / (1024^3), "\n")) } } .default_option_names <- function() { c("datatype", "filetype") #, "verbose") } terraOptions <- function(...) { dots <- list(...) if (is.null(.terra_environment$options)) .create_options() opt <- .terra_environment$options@ptr if (length(dots) == 0) { .showOptions(opt) } else { nms <- names(dots) d <- nms %in% .default_option_names() dnms <- paste0("def_", nms) for (i in 1:length(nms)) { if (d[i]) { opt[[ dnms[i] ]] <- dots[[ i ]] } else { opt[[ nms[i] ]] <- dots[[ i ]] } } if ("memfrac" %in% nms) { if (dots$memfrac > 0.9) { warn("terraOptions", "memfrac > 0.9") } } .terra_environment$options@ptr <- opt } } terra/R/relate.R0000644000175000017500000001343214201035747013327 0ustar nileshnilesh setMethod("is.related", signature(x="SpatVector", y="SpatVector"), function(x, y, relation) { out <- x@ptr$is_related(y@ptr, relation) x <- messages(x, "is.related") out } ) setMethod("is.related", signature(x="SpatVector", y="SpatExtent"), function(x, y, relation) { y <- as.polygons(y) out <- x@ptr$is_related(y@ptr, relation) x <- messages(x, "is.related") out } ) setMethod("relate", signature(x="SpatVector", y="SpatVector"), function(x, y, relation) { out <- x@ptr$relate_between(y@ptr, relation) x <- messages(x, "relate") out[out == 2] <- NA matrix(as.logical(out), nrow=nrow(x), byrow=TRUE) } ) setMethod("relate", signature(x="SpatVector", y="SpatExtent"), function(x, y, relation, ...) { y <- as.polygons(y) relate(x, y, relation, ...) } ) setMethod("relate", signature(x="SpatExtent", y="SpatVector"), function(x, y, relation, ...) { x <- as.polygons(x) relate(x, y, relation, ...) } ) setMethod("relate", signature(x="SpatExtent", y="SpatExtent"), function(x, y, relation, ...) { x <- as.polygons(x) y <- as.polygons(y) relate(x, y, relation, ...) } ) setMethod("relate", signature(x="SpatVector", y="missing"), function(x, y, relation, pairs=FALSE, symmetrical=FALSE) { out <- x@ptr$relate_within(relation, symmetrical) x <- messages(x, "relate") out[out == 2] <- NA if (symmetrical) { class(out) <- "dist" attr(out, "Size") <- nrow(x) attr(out, "Diag") <- FALSE attr(out, "Upper") <- FALSE } else { out <- matrix(as.logical(out), nrow=nrow(x), byrow=TRUE) } if (pairs) { out <- mat2wide(out, symmetrical) } out } ) setMethod("adjacent", signature(x="SpatRaster"), function(x, cells, directions="rook", pairs=FALSE, include=FALSE) { cells <- cells - 1 if (inherits(directions, "matrix")) { v <- x@ptr$adjacentMat(cells, as.logical(directions), dim(directions), include) } else { if (pairs) include <- FALSE v <- x@ptr$adjacent(cells, as.character(directions)[1], include) } messages(x, "adjacent") if (pairs) { v <- cbind(from=rep(cells, each=length(v)/length(cells)), to=v) v <- v[!is.na(v[,2]), ] } else { v <- matrix(v, nrow=length(cells), byrow=TRUE) if (!include) rownames(v) <- cells } v + 1 } ) setMethod("adjacent", signature(x="SpatVector"), function(x, type="rook", pairs=TRUE, symmetrical=FALSE) { type <- match.arg(tolower(type), c("intersects", "touches", "queen", "rook")) stopifnot(geomtype(x) == "polygons") a <- x@ptr$relate_within(type, TRUE) x <- messages(x, "relate") a[a == 2] <- NA class(a) <- "dist" attr(a, "Size") <- nrow(x) attr(a, "Diag") <- FALSE attr(a, "Upper") <- FALSE a <- as.matrix(a) if (pairs) { mat2wide(a, symmetrical, 1) } else { a } } ) setMethod("nearby", signature(x="SpatVector"), function(x, y=NULL, distance=0, k=1, centroids=TRUE, symmetrical=TRUE) { if ((geomtype(x) == "polygons") && centroids) { x <- centroids(x) } hasy <- !is.null(y) if (hasy) { if ((geomtype(y) == "polygons") && centroids) { y <- centroids(y) } } if (distance > 0) { if (hasy) { d <- distance(x, y) d <- cbind(from_id=rep(1:nrow(d), ncol(d)), to_id=rep(1:ncol(d), each=nrow(d)), distance=as.vector(d)) } else { d <- distance(x, pairs=TRUE, symmetrical=symmetrical) } d[d[,3] <= distance, 1:2, drop=FALSE] } else { if (hasy) { k <- max(1, min(round(k), (nrow(y)-1))) } else { k <- max(1, min(round(k), (nrow(x)-1))) } if (k > 1) { if (hasy) { d <- distance(x, y) } else { d <- as.matrix(distance(x, pairs=FALSE)) diag(d) <- NA } d <- t(apply(d, 1, function(i) order(i)[1:k])) if (k==1) d <- t(d) d <- cbind(1:length(x), d) } else { d <- nearest(x) d <- values(d)[, c("from_id", "to_id")] } colnames(d) <- c("id", paste0("k", 1:k)) d } } ) setMethod("nearest", signature(x="SpatVector"), function(x, y=NULL, pairs=FALSE, centroids=TRUE, lines=FALSE) { if ((geomtype(x) == "polygons") && centroids) { x <- centroids(x) } within <- FALSE if (is.null(y)) { within <- TRUE y <- x } else { if ((geomtype(y) == "polygons") && centroids) { y <- centroids(y) } } z <- x if (within) { z@ptr <- x@ptr$near_within() } else { z@ptr <- x@ptr$near_between(y@ptr, pairs) } z <- messages(z, "nearest") if (geomtype(z) == "points") { #lonlat points if (lines) { x <- z[,c(2,5), drop=TRUE] y <- z[,c(3,6), drop=TRUE] geom <- cbind(rep(1:nrow(x), each=2), 1, as.vector(t(x)), as.vector(t(y))) zz <- vect(geom, "lines", crs=crs(z)) values(zz) <- values(z) zz$to_id = zz$to_id + 1 zz$from_id = zz$from_id + 1 return(zz) } else { z$to_id = z$to_id + 1 z$from_id = z$from_id + 1 return(z) } } else { if (lines) return(z) dis <- perim(z) z <- as.points(z) from <- z[seq(1, nrow(z), 2), ] to <- z[seq(2, nrow(z), 2), ] values(to) <- data.frame(id=1:nrow(to)) values(y) <- data.frame(to_id=1:nrow(y)) to_int <- as.data.frame(intersect(to, y)) to_int <- to_int[order(to_int[["id"]]), ] if (nrow(to_int) > nrow(to)) { to_int <- aggregate(to_int[, "to_id",drop=FALSE], to_int[,"id",drop=FALSE], function(x)x[1]) } if (nrow(to_int) < nrow(to)) { to_int <- rep(NA, nrow(to)) } else { to_int <- to_int[,2] } from <- geom(from)[, c("x", "y"),drop=FALSE] to <- geom(to)[, c("x", "y"),drop=FALSE] d <- data.frame(1:nrow(from), from, to_int, to, dis) colnames(d) <- c("from_id", "from_x", "from_y", "to_id", "to_x", "to_y", "distance") vect(d, c("to_x", "to_y"), crs=crs(x)) } } ) terra/R/tempfiles.R0000644000175000017500000000266214201035747014046 0ustar nileshnilesh .orphanTmpFiles <- function() { objects <- ls(envir=globalenv()) ftmp <- list() for (i in seq_along(objects)) { x <- get(objects[i], envir=globalenv()) if (inherits(x, "SpatRaster")) { ftmp[[i]] <- sources(x) } } ftmp <- unique(unlist(ftmp)) ftmp <- ftmp[ftmp != ""] pattrn <- "^spat_.*tif$" i <- grep(pattrn, basename(ftmp)) ftmp <- ftmp[i] ff <- list.files(tempdir(), pattern=pattrn, full.names=TRUE) i <- !(basename(ff) %in% basename(ftmp)) ff[i] } tmpFiles <- function(current=TRUE, orphan=FALSE, old=FALSE, remove=FALSE) { if (!(old | current | orphan)) { error("tmpFiles", "at least one of 'orphan', 'current' and 'old' must be set to TRUE") } opt <- spatOptions() d <- opt$tempdir f <- NULL if (old) { if (normalizePath(tempdir()) != normalizePath(d)) { warn("tmpFiles", "old files can only be found if terra uses the R tempdir") } else { f <- list.files(dirname(d), recursive=TRUE, pattern="^spat_", full.names=TRUE) f <- grep("Rtmp", f, value=TRUE) if ((length(f) > 0) && (!current)) { i <- grep(d, f) if (length(i) > 0) { f <- f[-i] } } } } if (current) { ff <- list.files(d, pattern="^spat", full.names=TRUE) f <- c(f, ff) } else if (orphan) { fo <- .orphanTmpFiles() f <- c(f, fo) # for if old=TRUE } if (remove) { file.remove(f) return(invisible(f)) } else { return(f) } } terra/R/SpatRasterDataset.R0000644000175000017500000001450214201035747015450 0ustar nileshnilesh setMethod("length", signature(x="SpatRasterDataset"), function(x) { x@ptr$nsds() } ) setMethod("sds", signature(x="character"), function(x, ids=0) { if (length(x) > 1) { r <- lapply(x, rast) s <- sds(r) names(s) <- tools::file_path_sans_ext(basename(x)) return(s) } x <- trimws(x[1]) if (nchar(x) == 0) { error("sds", "provide valid file name(s)") } f <- .fullFilename(x) r <- methods::new("SpatRasterDataset") ids <- round(ids)-1 if (ids[1] < 0) { useids <- FALSE } else { useids <- TRUE } r@ptr <- SpatRasterStack$new(f, ids, useids) messages(r, "sds") } ) setMethod("sds", signature(x="missing"), function(x) { r <- methods::new("SpatRasterDataset") r@ptr <- SpatRasterStack$new() r } ) setMethod("sds", signature(x="SpatRaster"), function(x, ...) { r <- methods::new("SpatRasterDataset") r@ptr <- SpatRasterStack$new() r@ptr$add(x@ptr, varnames(x)[1], longnames(x)[1], units(x)[1], FALSE) dots <- list(...) nms <- names(dots) if (is.null(nms)) nms = "" nms <- rep_len(nms, length(dots)) for (i in seq_along(dots)) { if (inherits(dots[[i]], "SpatRaster")) { r@ptr$add(dots[[i]]@ptr, nms[i], "", "", FALSE) } } messages(r, "sds") } ) setMethod("sds", signature(x="list"), function(x) { r <- methods::new("SpatRasterDataset") r@ptr <- SpatRasterStack$new() nms <- names(x) if (is.null(nms)) nms <- rep("", length(x)) for (i in seq_along(x)) { if (inherits(x[[i]], "SpatRaster")) { r@ptr$add(x[[i]]@ptr, nms[i], "", "", FALSE) } } messages(r, "sds") } ) setMethod("sds", signature(x="array"), function(x, crs="", extent=NULL) { dims <- dim(x) if (length(dims) <= 3) { return(sds(rast(x, crs=crs, extent=extent))) } if (length(dims) > 4) { if (length(dims) == 5) { if (dims[5] == 1) { x <- x[,,,,1] } else { error("sds,array", "cannot handle an array with 5 dimensions") } } else { error("sds,array", "cannot handle an array with more than 4 dimensions") } } r <- lapply(1:dims[4], function(i) rast(x[,,,i], crs=crs, extent=extent)) sds(r) } ) setMethod("sds", signature(x="stars"), function(x) { s <- from_stars(x) if (inherits(s, "SpatRaster")) { sds(s) } else { s } } ) setMethod("sds", signature(x="stars_proxy"), function(x) { s <- from_stars(x) if (inherits(s, "SpatRaster")) { sds(s) } else { s } } ) setMethod("c", signature(x="SpatRasterDataset"), function(x, ...) { x@ptr <- x@ptr$subset((1:x@ptr$nsds()) -1 ) # why? make a copy? dots <- list(...) nms <- names(dots) for (i in seq_along(dots)) { if (inherits(dots[[i]], "SpatRasterDataset")) { sdsnms <- names(dots[[i]]) for (j in 1:(length(dots[[i]]))) { if (!x@ptr$add(dots[[i]][[j]]@ptr, sdsnms[j], "", "", FALSE)) { messages(x, "c") } } } else if (inherits(dots[[i]], "SpatRaster")) { if (is.null(nms)) error("c", "arguments must be named") if (!x@ptr$add(dots[[i]]@ptr, nms[i], "", "", FALSE)) { messages(x, "c") } } else { error("c", "arguments must be SpatRaster or SpatRasterDataset") } } messages(x, "c") } ) setReplaceMethod("[", c("SpatRasterDataset","numeric","missing"), function(x, i, j, value) { if (any(!is.finite(i)) | any(i<1)) { error("`[`", "invalid index") } stopifnot(inherits(value, "SpatRaster")) i <- sort(i) for (j in i) { if (j == (length(x)+1)) { x@ptr$add(value@ptr, "", "", "", FALSE) } else { x@ptr$replace(j-1, value@ptr) } } messages(x, "`[`") } ) setMethod("[", c("SpatRasterDataset", "numeric", "missing"), function(x, i, j, ... ,drop=TRUE) { i <- positive_indices(i, length(x), " [ ") if (drop && (length(i) == 1)) { ptr <- x@ptr$getsds(i-1) x <- rast() x@ptr <- ptr } else { x@ptr <- x@ptr$subset(i-1) } messages(x, "`[`") }) setMethod("[", c("SpatRasterDataset", "numeric", "numeric"), function(x, i, j, ... ,drop=TRUE) { y <- x[i,drop=drop] if (inherits(y, "SpatRaster")) { return(y[[j]]) } nd <- y@ptr$nsds() x@ptr <- SpatRasterStack$new() nms <- y@ptr$names for (k in seq_along(1:nd)) { r <- y[k][[j]] x@ptr$add(r@ptr, nms[k], "", "", FALSE) } messages(x, "`[`") }) setMethod("[", c("SpatRasterDataset", "logical", "missing"), function(x, i, j, ... ,drop=TRUE) { x[which(i), ..., drop=drop] }) setMethod("[", c("SpatRasterDataset", "character", "missing"), function(x, i, j, ... ,drop=TRUE) { i <- match(i, names(x)) if (any(is.na(i))) { error("`[`", "unknown name(s) provided") } x[i, ..., drop=drop] }) setMethod("[[", c("SpatRasterDataset", "ANY", "ANY"), function(x, i, j, ... ,drop=TRUE) { mi <- missing(i) mj <- missing(j) if ((mi) && (mj)) { `[`(x, ..., drop=drop) } else if (mi) { `[`(x, j=j, ..., drop=drop) } else if (mj) { `[`(x, i=i, ..., drop=drop) } else { `[`(x, i=i, j=j, ..., drop=drop) } }) setMethod("$", "SpatRasterDataset", function(x, name) { x[name] } ) setMethod("sprc", signature(x="missing"), function(x) { r <- methods::new("SpatRasterCollection") r@ptr <- SpatRasterCollection$new() r } ) setMethod("sprc", signature(x="SpatRaster"), function(x, ...) { sprc(list(x, ...)) } ) setMethod("sprc", signature(x="list"), function(x) { n <- length(x) ptr <- SpatRasterCollection$new() if (n > 0) { for (i in 1:n) { if (inherits(x[[i]], "SpatRaster")) { ptr$add(x[[i]]@ptr) } else { name <- names(x[[i]]) cls <- class(x[[i]]) error("sprc", "list elements should be 'SpatRaster'\n", name, "is of class: ", cls) } } } x <- new("SpatRasterCollection") x@ptr <- ptr x } ) setMethod("length", signature(x="SpatRasterCollection"), function(x) { x@ptr$length() } ) setMethod("[", c("SpatRasterCollection", "numeric", "missing"), function(x, i, j, ... ,drop=TRUE) { i <- positive_indices(i, length(x), " [ ") if (drop && (length(i) == 1)) { ptr <- x@ptr$x[i][[1]] x <- rast() x@ptr <- ptr } else { s <- x@ptr$x[i] ptr <- SpatRasterCollection$new() for (i in 1:length(s)) { ptr$add(s[[i]]) } x@ptr <- ptr } messages(x, "`[`") }) terra/R/plot.R0000644000175000017500000002116214202245434013025 0ustar nileshnilesh .one.density <- function(x, maxcells=100000, plot=TRUE, ...) { d <- values(x) d <- stats::density(stats::na.omit(d)) if (plot) { plot(d, ...) return(invisible(d)) } else { return(d) } } setMethod("density", signature(x="SpatRaster"), function(x, maxcells=100000, plot=TRUE, main, ...) { x <- spatSample(x, maxcells, method="regular", as.raster=TRUE) res <- list() nl <- nlyr(x) if (missing(main)) { main=names(x) } else { main <- rep(main, length.out=nl) } if (nl==1) { res[[1]] <- .one.density(x, plot=plot, maxcells=maxcells, main=main, ...) } else { if (nl > 16) { warn("density", "only the first 16 layers are plotted") nl <- 16 x <- x[[1:16]] } nc <- ceiling(sqrt(nl)) nr <- ceiling(nl / nc) mfrow <- graphics::par("mfrow") spots <- mfrow[1] * mfrow[2] if (spots < nl) { old.par <- graphics::par(no.readonly = TRUE) on.exit(graphics::par(old.par)) graphics::par(mfrow=c(nr, nc)) } for (i in 1:nlyr(x)) { res[[i]] <- .one.density(x[[i]], maxcells=maxcells, main=main[i], plot=plot, ...) } } if (plot) return(invisible(res)) else return(res) } ) setMethod("persp", signature(x="SpatRaster"), function(x, maxcells=100000, ...) { x <- spatSample(x, size=maxcells, method="regular", as.raster=TRUE) value <- t(as.matrix(x, wide=TRUE)[nrow(x):1,]) y <- yFromRow(x, nrow(x):1) x <- xFromCol(x, 1:ncol(x)) graphics::persp(x=x, y=y, z=value, ...) } ) .plot.filled.contour <- function(x, maxcells=100000, ...) { x <- spatSample(x[[1]], maxcells, method="regular", as.raster=TRUE) X <- xFromCol(x, 1:ncol(x)) Y <- yFromRow(x, nrow(x):1) Z <- t( matrix( values(x), ncol=ncol(x), byrow=TRUE)[nrow(x):1,] ) if (is.null(list(...)$asp)) { asp <- ifelse(is.lonlat(x, perhaps=TRUE, warn=FALSE), 1/cos((mean(as.vector(ext(x))[3:4]) * pi)/180), 1) graphics::filled.contour(x=X, y=Y, z=Z, asp=asp, ...) } else { graphics::filled.contour(x=X, y=Y, z=Z,...) } } setMethod("contour", signature(x="SpatRaster"), function(x, maxcells=100000, filled=FALSE, ...) { if (filled) { .plot.filled.contour(x, maxcells=maxcells, ...) } else { x <- spatSample(x[[1]], maxcells, method="regular", as.raster=TRUE) if (is.null(list(...)$asp)) { asp <- ifelse(is.lonlat(x, perhaps=TRUE, warn=FALSE), 1/cos((mean(as.vector(ext(x))[3:4]) * pi)/180), 1) graphics::contour(x=xFromCol(x,1:ncol(x)), y=yFromRow(x, nrow(x):1), z=t(as.matrix(x, wide=TRUE)[nrow(x):1,]), asp=asp, ...) } else { graphics::contour(x=xFromCol(x,1:ncol(x)), y=yFromRow(x, nrow(x):1), z=t(as.matrix(x, wide=TRUE)[nrow(x):1,]), ...) } } } ) setMethod("as.contour", signature(x="SpatRaster"), function(x, maxcells=100000, ...) { x <- spatSample(x[[1]], size=maxcells, method="regular", as.raster=TRUE) z <- grDevices::contourLines(x=xFromCol(x,1:ncol(x)), y=yFromRow(x, nrow(x):1), z=t(as.matrix(x, wide=TRUE)[nrow(x):1,]), ...) y <- sapply(1:length(z), function(i) cbind(z[[i]]$level, i, z[[i]]$x, z[[i]]$y)) y <- do.call(rbind, y) y[] <- as.numeric(y) u <- unique(y[,1]) y[,1] <- match(y[,1], u) colnames(y)[3:4] <- c("x", "y") vect(y, "lines", atts=data.frame(level=u), crs=crs(x)) } ) setMethod("pairs", signature(x="SpatRaster"), function(x, hist=TRUE, cor=TRUE, use="pairwise.complete.obs", maxcells=100000, ...) { if (nlyr(x) < 2) { error("x must have at least two layers") } if (nlyr(x) < 2) { error("x must have at least two layers") } panelhist <- function(x,...) { usr <- graphics::par("usr") on.exit(graphics::par(usr=usr)) graphics::par(usr = c(usr[1:2], 0, 1.5) ) h <- hist(x, plot = FALSE) breaks <- h$breaks nB <- length(breaks) y <- h$counts y <- y/max(y) graphics::rect(breaks[-nB], 0, breaks[-1], y, col="green") } panelcor <- function(x, y,...) { usr <- graphics::par("usr") on.exit(graphics::par(usr=usr)) graphics::par(usr = c(0, 1, 0, 1)) r <- abs(stats::cor(x, y, use=use)) txt <- format(c(r, 0.123456789), digits=2)[1] text(0.5, 0.5, txt, cex = max(0.5, r * 2)) } if (hist) {dp <- panelhist} else {dp <- NULL} if (cor) {up <- panelcor} else {up <- NULL} d <- spatSample(x, maxcells, method="regular", as.raster=FALSE) dots <- list(...) cex <- dots$cex main <- dots$main if (is.null(cex)) cex <- 0.5 if (is.null(main)) main <- "" graphics::pairs(d, main=main, cex=cex, upper.panel=up, diag.panel=dp) } ) .halo <- function(x, y=NULL, labels, col="black", hc="white", hw=0.1, ... ) { xy <- grDevices::xy.coords(x, y) xo <- hw * graphics::strwidth("A") yo <- hw * graphics::strheight("A") n <- nchar(labels) theta <- seq(pi/4, 2*pi, length.out=8*hw*10) for (i in theta) { text( xy$x + cos(i)*xo, xy$y + sin(i)*yo, labels, col=hc, ... ) } graphics::text(xy$x, xy$y, labels, col=col, ... ) } setMethod("text", signature(x="SpatRaster"), function(x, labels, digits=0, halo=FALSE, ...) { if (missing(labels)) { labels <- 1 } if (length(labels) != ncell(x)) { labels <- labels[1] if (is.character(labels)) { i <- which(labels == names(x)) if (i == 0) { i <- 1 } } x <- x[[labels]] labels <- as.data.frame(x)[,1] p <- as.points(x, values=TRUE) } else { p <- as.points(x, values=FALSE, na.rm=FALSE) } xy <- geom(p)[, c("x", "y")] if (is.factor(labels)) { labels <- substr(as.character(labels), 1, max(1, digits)) } else if (is.numeric(labels)) { labels <- as.character(round(labels, digits=digits) ) } if (halo) { .halo(xy[,1], xy[,2], labels, ...) } else { text(xy[,1], xy[,2], labels, ...) } } ) setMethod("text", signature(x="SpatVector"), function(x, labels, halo=FALSE, ...) { if (missing(labels)) { labels <- 1:nrow(x) } else if (length(labels) == 1) { if (nrow(x) > 1) { labels <- as.data.frame(x)[,labels] } else { if (is.numeric(labels)) { if (labels %in% 1:ncol(x)) { labels <- x[[labels]][,1] } } else if (labels %in% names(x)) { labels <- x[[labels]][,1] } } } xy <- geom(centroids(x))[,c("x","y"),drop=FALSE] if (halo) { .halo(xy[,1], xy[,2], labels, ...) } else { text(xy[,1], xy[,2], labels, ...) } } ) setMethod("boxplot", signature(x="SpatRaster"), function(x, y=NULL, maxcell=100000, ...) { if (is.null(y)) { cn <- names(x) if ( ncell(x) > maxcell) { warn("boxplot", "taking a sample of ", maxcell, " cells") x <- spatSample(x, maxcell, method="regular", as.raster=TRUE) } names(x) <- cn boxplot(values(x), ...) } else { s <- c(x[[1]], y[[1]]) if ( ncell(x) > maxcell) { warn("boxplot", "taking a regular sample of ", maxcell, " cells") s <- spatSample(s, maxcell, method="regular", as.raster=TRUE) } s <- values(s, dataframe=TRUE) cn <- colnames(s) if (is.null(cn)) cn <- c("", "") colnames(s)[cn==""] <- c("layer1", "layer2")[cn==""] f <- try(stats::as.formula(paste(cn[1], '~', cn[2])), silent=TRUE) if (inherits(f, "try-error")) { colnames(s) <- c("layer1", "layer2") f <- layer1 ~ layer2 } boxplot(f, data=s, ...) } } ) setMethod("barplot", "SpatRaster", function(height, maxcell=1000000, digits=0, breaks=NULL, col, ...) { if (missing(col)) { col=grDevices::rainbow } height <- height[[1]] f <- is.factor(height) x <- spatSample(height[[1]], maxcell, method="regular", as.raster=FALSE, as.df=f) x <- spatSample(height[[1]], maxcell, method="regular", as.raster=FALSE, as.df=FALSE) adj <- nrow(x) / ncell(height) if (adj < 1) { warn("barplot", "a sample of ", round(100*adj, 1), "% of the raster cells were used to estimate frequencies") } if (!f) { if (!is.null(digits)) { x <- round(x, digits) } if (!is.null(breaks)) { x <- cut(x, breaks) } } x <- table(x) / adj if (is.function(col)) { col <- col(length(x)) } barplot(x, col=col, ...) } ) shade <- function(slope, aspect, angle=45, direction=0, normalize=FALSE, filename="", ...) { x <- c(slope[[1]], aspect[[1]]) direction <- direction[1] * pi/180 zenith <- (90 - angle[1]) * pi/180 if (normalize) { fun <- function(slp, asp) { shade <- cos(slp) * cos(zenith) + sin(slp) * sin(zenith) * cos(direction-asp) shade[shade < 0] <- 0 shade * 255 } } else { fun <- function(slp, asp) { cos(slp) * cos(zenith) + sin(slp) * sin(zenith) * cos(direction-asp) } } lapp(x, fun=fun, filename=filename, wopt=list(...)) } terra/R/interpolate.R0000644000175000017500000000307014201035747014376 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : August 2009 # Version 0.9 # License GPL v3 setMethod("interpolate", signature(object="SpatRaster"), function(object, model, fun=predict, ..., xyNames=c("x", "y"), factors=NULL, const=NULL, index=NULL, na.rm=FALSE, filename="", overwrite=FALSE, wopt=list()) { out <- rast(object) hv <- hasValues(object) nms <- c(xyNames, names(object)) if (length(unique(nms)) != length(nms)) { tab <- table(nms) error("interpolate", "duplicate names: ", tab[tab>1]) } nc <- ncol(out) testrow <- round(0.51*nrow(object)) ntest <- min(nc, 500) xy <- xyFromCell(out, cellFromRowCol(out, testrow, 1):cellFromRowCol(out, testrow, ntest)) colnames(xy) <- xyNames if (hv) { readStart(object) on.exit(readStop(object)) d <- readValues(object, testrow, 1, 1, ntest, TRUE, TRUE) xy <- cbind(xy, d) } r <- .runModel(model, fun, xy, 1, const, (na.rm & hv), index, ...) nl <- ncol(r) out <- rast(object, nlyrs=nl) cn <- colnames(r) if (length(cn) == nl) names(out) <- make.names(cn, TRUE) b <- writeStart(out, filename, overwrite, wopt=wopt) for (i in 1:b$n) { xy <- xyFromCell(out, cellFromRowCol(out, b$row[i], 1):cellFromRowCol(out, b$row[i]+b$nrows[i]-1, nc)) colnames(xy) <- xyNames if (hv) { d <- readValues(object, b$row[i], b$nrows[i], 1, nc, TRUE, TRUE) xy <- cbind(xy, d) } v <- .runModel(model, fun, xy, nl, const, (na.rm & hv), index, ...) writeValues(out, v, b$row[i], b$nrows[i]) } out <- writeStop(out) return(out) } ) terra/R/plot_cartogram.R0000644000175000017500000000075014201035747015067 0ustar nileshnilesh setMethod("cartogram", signature(x="SpatVector"), function(x, var, type) { type <- match.arg(tolower(type), "nc") stopifnot(var %in% names(x)) v <- as.numeric(as.vector(x[[var, drop=TRUE]])) if (!any(!is.na(v))) stop(paste("no numeric values in", var)) if (any(v <= 0)) stop(paste("non-positive values in", var)) x <- x[!is.na(v)] v <- v[!is.na(v)] f <- v / max(v) r <- lapply(1:length(v), function(i) rescale(x[i,], f[i])) do.call(rbind, r) } ) terra/R/window.R0000644000175000017500000000110414201035747013353 0ustar nileshnilesh setMethod("window<-", signature(x="SpatRaster"), function(x, value) { if (inherits(value, "SpatExtent")) { value <- value * ext(x) if (!(x@ptr$setWindow(value@ptr))) { error("window<-,SpatRaster", "could not set window") } #warn("window<-", "using a window is experimental") } else if (is.null(value) || is.na(value)) { x@ptr$removeWindow() } else { error("window<-", "'value' should be a SpatExtent, NULL or NA") } x } ) setMethod("window", signature(x="SpatRaster"), function(x) { x@ptr$hasWindow() } ) terra/R/cells.R0000644000175000017500000000366514201035747013164 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : June 2020 # Version 1.0 # License GPL v3 setMethod("cells", signature(x="SpatRaster", y="missing"), function(x, y) { # is this useful? which(!is.na(values(x))) } ) setMethod("cells", signature(x="SpatRaster", y="numeric"), function(x, y) { opt <- spatOptions() v <- x@ptr$is_in_cells(y, opt) x <- messages(x, "cells") v <- lapply(v, function(i) i+1) names(v) <- names(x) v } ) setMethod("cells", signature("SpatRaster", "SpatVector"), function(x, y, method="simple", weights=FALSE, exact=FALSE, touches=is.lines(y)) { method = match.arg(tolower(method), c("simple", "bilinear")) opt <- spatOptions() d <- x@ptr$vectCells(y@ptr, touches[1], method[1], weights[1], exact[1], opt) if (geomtype(y) == "points") { d <- matrix(d, nrow=nrow(y), byrow=TRUE) d <- cbind(1:nrow(y), d) if (method == "bilinear") { colnames(d) <- c("ID", "c1", "c2", "c3", "c4", "w1", "w2", "w3", "w4") d[,2:5] <- d[,2:5] + 1 } else { colnames(d) <- c("ID", "cell") d[,2] <- d[,2] + 1 } return (d) } cn <- c("ID", "cell") if (weights[1] || exact[1]) { d <- matrix(d, ncol=3) cn <- c(cn, "weights") } else { d <- matrix(d, ncol=2) } d[,1:2] <- d[,1:2] + 1 colnames(d) <- cn d } ) #setMethod("cells", signature("SpatRaster", "SpatExtent"), # function(x, y, ...) { # p <- as.polygons(y, crs=crs(x)) # cells(x, p)[,2] # } #) #setMethod("cells", signature("SpatRaster", "SpatExtent"), # function(x, y, ...) { # e <- align(y, x) # s <- res(x)/2 # e <- as.vector(y) + c(s[1], -s[1], s[2], -s[2]) # r <- rowFromY(x, e[4:3])-1 # c <- colFromX(x, e[1:2]) # cc <- c[1]:c[2] # rr <- (r[1]:r[2]) * ncol(x) # rep(rr, each=length(cc)) + cc # } #) setMethod("cells", signature("SpatRaster", "SpatExtent"), function(x, y) { opt <- spatOptions() x@ptr$extCells(y@ptr) + 1 } ) terra/R/ncdf.R0000644000175000017500000003544014202047450012763 0ustar nileshnilesh .ncdf_extent <- function(x) { if (!("ncdf4" %in% rownames(utils::installed.packages()))) { warn("rast", "GDAL did not find an extent. installing the ncdf4 package may help") return(x) } fname <- sources(x)[1] zvar <- varnames(x) dims <- 1:3 nc <- ncdf4::nc_open(fname, readunlim=FALSE, suppress_dimvals = TRUE) on.exit( ncdf4::nc_close(nc) ) ncols <- nc$var[[zvar]]$dim[[dims[1]]]$len nrows <- nc$var[[zvar]]$dim[[dims[2]]]$len if (!(ncol(x) == ncols) & (nrow(x) == nrows)) { warn("rast", "GDAL did not find an extent. Cells not equally spaced?") return(x) } xx <- try(ncdf4::ncvar_get(nc, nc$var[[zvar]]$dim[[dims[1]]]$name), silent = TRUE) if (inherits(xx, "try-error")) { xx <- seq_len(nc$var[[zvar]]$dim[[dims[1]]]$len) } rs <- xx[-length(xx)] - xx[-1] if (! isTRUE ( all.equal( min(rs), max(rs), tolerance=0.025, scale= abs(min(rs))) ) ) { warn("rast", "cells are not equally spaced; extent is not defined") return(x) } xrange <- c(min(xx), max(xx)) resx <- (xrange[2] - xrange[1]) / (ncols-1) yy <- try(ncdf4::ncvar_get(nc, nc$var[[zvar]]$dim[[dims[2]]]$name), silent = TRUE) if (inherits(yy, "try-error")) { yy <- seq_len(nc$var[[zvar]]$dim[[dims[2]]]$len) } rs <- yy[-length(yy)] - yy[-1] if (! isTRUE ( all.equal( min(rs), max(rs), tolerance=0.025, scale= abs(min(rs))) ) ) { warn("rast", "cells are not equally spaced; extent is not defined") return(x) } yrange <- c(min(yy), max(yy)) resy <- (yrange[2] - yrange[1]) / (nrows-1) xrange[1] <- xrange[1] - 0.5 * resx xrange[2] <- xrange[2] + 0.5 * resx yrange[1] <- yrange[1] - 0.5 * resy yrange[2] <- yrange[2] + 0.5 * resy ext(x) <- ext(xrange[1], xrange[2], yrange[1], yrange[2]) return(x) } .write_cdf <- function(x, filename, overwrite=FALSE, zname="time", prec="float", compression=NA, missval, ...) { dots <- list(...) force_v4 <- isTRUE(dots$force_v4) verbose <- isTRUE(dots$verbose) n <- length(x) y <- x[1] if (is.lonlat(y, perhaps=TRUE, warn=FALSE)) { xname = "longitude" yname = "latitude" xunit = "degrees_east" yunit = "degrees_north" } else { xname = "easting" yname = "northing" xunit = "meter" # probably yunit = "meter" # probably } xdim <- ncdf4::ncdim_def( xname, xunit, xFromCol(y, 1:ncol(y)) ) ydim <- ncdf4::ncdim_def( yname, yunit, yFromRow(y, 1:nrow(y)) ) vars <- varnames(x) vars[vars == ""] <- paste0("var_", (1:n)[vars == ""]) vars <- make.unique(vars) lvar <- longnames(x) units <- units(x) zname <- rep_len(zname, n) valid_prec <- c("short", "integer", "float", "double", "byte") if (!all(prec %in% valid_prec)) { error("writeCDF", paste("prec must be one of:", paste(valid_prec, collapse=", "))) } prec <- rep_len(prec, n) if (missing(missval)) { miss_vals <- c(-32768, -2147483647, -1.175494e38, -1.7976931348623157e308, 255) missval <- miss_vals[match(prec, valid_prec)] } else { missval <- rep_len(missval, n) } compression <- compression[1] nc <- ncol(x) nr <- nrow(x) nl <- nlyr(x) ncvars <- list() cal <- NA for (i in 1:n) { if ((nl[i] > 1) || (x[i]@ptr$hasTime)) { y <- x[i] if (y@ptr$hasTime) { zv <- y@ptr$time tstep <- y@ptr$timestep cal <- "standard" if (tstep == "seconds") { zunit <- "seconds since 1970-1-1 00:00:00" cal <- "standard" } else if (tstep == "days") { zunit <- "days since 1970-1-1" cal <- "standard" } else { zunit <- "unknown" } } else { zv <- 1:nlyr(y) zunit <- "unknown" } zdim <- ncdf4::ncdim_def(zname[i], zunit, zv, unlim=FALSE, create_dimvar=TRUE, calendar=cal) ncvars[[i]] <- ncdf4::ncvar_def(vars[i], units[i], list(xdim, ydim, zdim), missval[i], lvar[i], prec = prec[i], compression=compression,...) } else { ncvars[[i]] <- ncdf4::ncvar_def(name=vars[i], units=units[i], dim=list(xdim, ydim), missval=missval[i], longname=lvar[i], prec = prec[i], compression=compression, ...) } } ncvars[[n+1]] <- ncdf4::ncvar_def("crs", "", list(), NULL, prec="integer") ncobj <- ncdf4::nc_create(filename, ncvars, force_v4=force_v4, verbose=verbose) on.exit(ncdf4::nc_close(ncobj)) prj <- crs(x[1]) prj <- gsub("\n", "", prj) if (prj != "") { ncdf4::ncatt_put(ncobj, ncvars[[n+1]], "crs_wkt", prj, prec="text") # need for older gdal? ncdf4::ncatt_put(ncobj, ncvars[[n+1]], "spatial_ref", prj, prec="text") ncdf4::ncatt_put(ncobj, ncvars[[n+1]], "proj4", .proj4(x[1]), prec='text') } e <- ext(x) rs <- res(x) gt <- paste(trimws(formatC(as.vector(c(e$xmin, rs[1], 0, e$ymax, 0, -1 * rs[2])), 22)), collapse=" ") ncdf4::ncatt_put(ncobj, ncvars[[n+1]], "GeoTransform", gt, prec="text") opt <- spatOptions() for (i in 1:n) { y = x[i] readStart(y) b <- blockSize(y, 4) if (length(ncvars[[1]]$dim) == 3) { for (j in 1:b$n) { d <- readValues(y, b$row[j], b$nrows[j], 1, nc, FALSE, FALSE) d <- array(d, c(nc, b$nrows[j], nl[i])) ncdf4::ncvar_put(ncobj, ncvars[[i]], d, start=c(1, b$row[j], 1), count=c(nc, b$nrows[j], nl[i])) } } else { for (j in 1:b$n) { d <- readValues(y, b$row[j], b$nrows[j], 1, nc, FALSE, FALSE) d <- matrix(d, ncol=b$nrows[j]) ncdf4::ncvar_put(ncobj, ncvars[[i]], d, start=c(1, b$row[j]), count=c(nc, b$nrows[j])) } } readStop(y) if (prj != "") { ncdf4::ncatt_put(ncobj, ncvars[[i]], "grid_mapping", "crs", prec="text") } } ncdf4::ncatt_put(ncobj, 0, "Conventions", "CF-1.4", prec="text") pkgversion <- drop(read.dcf(file=system.file("DESCRIPTION", package="terra"), fields=c("Version"))) ncdf4::ncatt_put(ncobj, 0, "created_by", paste("R, packages ncdf4 and terra (version ", pkgversion, ")", sep=""), prec="text") ncdf4::ncatt_put(ncobj, 0, "date", format(Sys.time(), "%Y-%m-%d %H:%M:%S"), prec="text") TRUE } setMethod("writeCDF", signature(x="SpatRaster"), function(x, filename, varname, longname="", unit="", ...) { filename <- trimws(filename) stopifnot(filename != "") if (missing(varname)) { varname <- tools::file_path_sans_ext(basename(filename)) } varnames(x) <- varname longnames(x) <- longname units(x) <- unit x <- sds(x) invisible( writeCDF(x, filename=filename, ...) ) } ) setMethod("writeCDF", signature(x="SpatRasterDataset"), function(x, filename, overwrite=FALSE, zname="time", prec="float", compression=NA, missval, ...) { filename <- trimws(filename) stopifnot(filename != "") xt <- tools::file_ext(filename) if (!(xt %in% c("nc", "cdf"))) { warn("writeCDF", "for better results use file extension '.nc' or '.cdf'\nsee: https://stackoverflow.com/a/65398262/635245") } if (file.exists(filename) & !overwrite) { error("writeCDF", "file exists, use 'overwrite=TRUE' to overwrite it") } ok <- .write_cdf(x, filename, zname=zname, prec=prec, compression=compression, missval=missval, ...) if (ok) { if (length(x) > 1) { out <- sds(filename) } else { out <- rast(filename) } invisible(out) } else { error("writeCDF", "?") } } ) .varName <- function(nc, varname="", warn=TRUE) { n <- nc$nvars dims <- vars <- vector(length=n) if (n > 0) { for (i in 1:n) { vars[i] <- nc$var[[i]]$name dims[i] <- nc$var[[i]]$ndims } vars <- vars[dims > 1] dims <- dims[dims > 1] } if (varname=='') { nv <- length(vars) if (nv == 0) { return('z') } if (nv == 1) { varname <- vars } else { varname <- vars[which.max(dims)] if (warn) { if (sum(dims == max(dims)) > 1) { vars <- vars[dims==max(dims)] warning('varname used is: ', varname, '\nIf that is not correct, you can set it to one of: ', paste(vars, collapse=", ") ) } } } } zvar <- which(varname == vars) if (length(zvar) == 0) { stop('varname: ', varname, ' does not exist in the file. Select one from:\n', paste(vars, collapse=", ") ) } return(varname) } .getCRSfromGridMap4 <- function(g) { if (!is.null(g$epsg_code)) { crs <- g$epsg_code if (!grep("EPSG:", crs, ignore.case=TRUE)) { crs <- paste0("epsg:", crs) } return(crs) } sp <- g$standard_parallel if (length(sp) > 1) { g$standard_parallel1 <- sp[1] g$standard_parallel2 <- sp[2] g$standard_parallel <- NULL } vals <- sapply(g, function(i) i[1]) vars <- names(vals) if (any(vars %in% c("proj4", "crs_wkt", "spatial_ref"))) { crs=vals[vars %in% c("proj4", "crs_wkt", "spatial_ref")][1] return(crs) } # based on info at # http://trac.osgeo.org/gdal/wiki/NetCDF_ProjectionTestingStatus # accessed 7 October 2012 prj <- matrix(c("albers_conical_equal_area", "aea", "azimuthal_equidistant", "aeqd", "lambert_cylindrical_equal_area", "cea", "lambert_azimuthal_equal_area", "laea", "lambert_conformal_conic", "lcc", "latitude_longitude", "longlat", "mercator", "merc", "orthographic", "ortho", "polar_stereographic", "stere", "stereographic", "stere", "transverse_mercator", "tmerc"), ncol=2, byrow=TRUE) m <- matrix(c("grid_mapping_name", "+proj", "false_easting", "+x_0","false_northing", "+y_0", "scale_factor_at_projection_origin", "+k_0", "scale_factor_at_central_meridian", "+k_0", "standard_parallel", "+lat_1", "standard_parallel1", "+lat_1", "standard_parallel2", "+lat_2", "longitude_of_central_meridian", "+lon_0", "longitude_of_projection_origin", "+lon_0", "latitude_of_projection_origin", "+lat_0", "straight_vertical_longitude_from_pole", "+lon_0", "longitude_of_prime_meridian", "+pm", "semi_major_axis", "+a", "semi_minor_axis", "+b", "inverse_flattening", "+rf", "earth_radius", "+a"), ncol=2, byrow=TRUE) # add logic that if prime merid is defined but not centr merid. centr merid is same as prime. i <- match(vars, m[,1]) if (all(is.na(i))) { gg <- cbind(vars, vals) mtxt <- paste(apply(gg, 1, function(x) paste(x, collapse='=')), collapse='; ') warning("cannot process the crs\n", mtxt) return(NA) } else if (any(is.na(i))) { vr <- vars[is.na(i)] vl <- vals[is.na(i)] gg <- cbind(vr, vl) gg <- gg[!(gg[,1] %in% c("crs_wkt", "esri_pe_string")), ,drop=FALSE] if (NROW(gg) > 0) { mtxt <- paste(apply(gg, 1, function(x) paste(x, collapse='=')), collapse='\n') warning("cannot process these parts of the crs:\n", mtxt) } vars <- vars[!is.na(i)] vals <- vals[!is.na(i)] i <- stats::na.omit(i) } tab <- cbind(m[i,], vals) rr <- which(tab[,1] == "earth_radius") if (length(rr) > 0) { bb <- tab[rr,] bb[2] <- "+b" tab <- rbind(tab, bb) } p <- which(tab[,2] == '+proj') if (length(p) == 0) { warning("cannot create a valid crs\n", mtxt) return(NA) } else { tab <- rbind(tab[p, ], tab[-p, ]) } j <- match(tab[1,3], prj[,1]) tab[1,3] <- prj[j,2] cr <- paste(apply(tab[,2:3], 1, function(x) paste(x, collapse='=')), collapse=' ') crtst <- try(rast(crs=cr), silent=TRUE) if ( inherits(crtst, "try-error")) { mtxt <- paste(m, collapse='; ') warning("cannot create a valid crs\n", mtxt) return(NA) } else { return(cr) } } .ncdfTime <- function(nc, zvar, dim3, zval) { dodays <- TRUE dohours <- FALSE doseconds <- FALSE un <- nc$var[[zvar]]$dim[[dim3]]$units if (substr(un, 1, 10) == "days since") { startDate = as.Date(substr(un, 12, 22)) } else if (substr(un, 1, 11) == "hours since") { dohours <- TRUE dodays <- FALSE startTime <- substr(un, 13, 30) mult <- 3600 } else if (substr(un, 1, 13) == "seconds since") { doseconds <- TRUE dodays <- FALSE startTime = as.Date(substr(un, 15, 31)) mult <- 1 } else if (substr(un, 1, 12) == "seconds from") { doseconds <- TRUE dodays <- FALSE startTime = as.Date(substr(un, 14, 31)) mult <- 1 } else { return(NULL) } if (!dodays) { start <- strptime(startTime, "%Y-%m-%d %H:%M:%OS", tz = "UTC") if (is.na(start)) start <- strptime(startTime, "%Y-%m-%d", tz = "UTC") if (is.na(start)) return(x) startTime <- start time <- startTime + as.numeric(zval) * mult time <- as.character(time) if (!is.na(time[1])) { return(time) } } else if (dodays) { # cal = nc$var[[zvar]]$dim[[dim3]]$calendar ? cal <- ncdf4::ncatt_get(nc, "time", "calendar") if (! cal$hasatt ) { greg <- TRUE } else { cal <- cal$value if (cal =='gregorian' | cal =='proleptic_gregorian' | cal=='standard') { greg <- TRUE } else if (cal == 'noleap' | cal == '365 day' | cal == '365_day') { greg <- FALSE nday <- 365 } else if (cal == '360_day') { greg <- FALSE nday <- 360 } else { greg <- TRUE warning('assuming a standard calender:', cal) } } if (greg) { time <- as.Date(time, origin=startDate) } else { startyear <- as.numeric( format(startDate, "%Y") ) startmonth <- as.numeric( format(startDate, "%m") ) startday <- as.numeric( format(startDate, "%d") ) year <- trunc( as.numeric(time)/nday ) doy <- (time - (year * nday)) origin <- paste(year+startyear, "-", startmonth, "-", startday, sep='') time <- as.Date(doy, origin=origin) } return(time) } return(NULL) } pointsCDF <- function(filename, varname, polygons=FALSE) { if (!("ncdf4" %in% rownames(utils::installed.packages()))) { warn("rast", "GDAL did not find an extent. installing the ncdf4 package may help") return(x) } zvar <- .varName(nc, varname, warn=TRUE) nc <- ncdf4::nc_open(filename, readunlim=FALSE, suppress_dimvals = TRUE) on.exit( ncdf4::nc_close(nc) ) dims <- 1:3 ncols <- nc$var[[zvar]]$dim[[dims[1]]]$len nrows <- nc$var[[zvar]]$dim[[dims[2]]]$len xx <- try(ncdf4::ncvar_get(nc, nc$var[[zvar]]$dim[[dims[1]]]$name), silent = TRUE) if (inherits(xx, "try-error")) { error("pointsCDF", "no x coordinates found") } yy <- try(ncdf4::ncvar_get(nc, nc$var[[zvar]]$dim[[dims[2]]]$name), silent = TRUE) if (inherits(yy, "try-error")) { error("pointsCDF", "no x coordinates found") } a <- ncdf4::ncatt_get(nc, zvar, "grid_mapping") prj <- NA if ( a$hasatt ) { try(atts <- ncdf4::ncatt_get(nc, a$value), silent=TRUE) try(prj <- .getCRSfromGridMap4(atts), silent=TRUE) } dim3 <- dims[3] dim3_vals <- try(ncdf4::ncvar_get(nc, nc$var[[zvar]]$dim[[dim3]]$name), silent = TRUE) if (inherits(dim3_vals, "try-error")) { dim3_vals <- seq_len(nc$var[[zvar]]$dim[[dim3]]$len) } nms <- NULL if ( nc$var[[zvar]]$dim[[dim3]]$name == "time" ) { try( nms <- .ncdfTime(nc, zvar, dim3, dim3_vals) ) } d <- ncdf4::ncvar_get( nc, varid=zvar) nl <- dim(d)[3] v <- sapply(1:nl, function(i) d[,,i]) natest1 <- ncdf4::ncatt_get(nc, zvar, "_FillValue") natest2 <- ncdf4::ncatt_get(nc, zvar, "missing_value") if (natest1$hasatt) { v[v==natest1$value] <- NA } else if (natest2$hasatt) { v[v==natest2$value] <- NA } if (!is.null(nms)) { colnames(v) <- nms } vect(cbind(rep(xx, length(yy)), rep(yy, each=length(xx))), atts=v, crs=prj) } terra/R/pack.R0000644000175000017500000000712714201035747012775 0ustar nileshnilesh setClass("PackedSpatVector", representation ( type = "character", crs = "character", coordinates = "matrix", index = "matrix", attributes = "data.frame" ), prototype ( type= "", crs = "" ) ) setClass("PackedSpatRaster", representation ( definition = "character", values = "matrix", attributes = "list" ), prototype ( attributes = list() ) ) .packVector <- function(x) { vd <- methods::new("PackedSpatVector") vd@type <- geomtype(x) vd@crs <- as.character(crs(x)) stopifnot(vd@type %in% c("points", "lines", "polygons")) g <- geom(x) vd@coordinates <- g[, c("x", "y")] j <- c(1,2, grep("hole", colnames(g))) g <- g[,j] i <- which(!duplicated(g)) vd@index <- cbind(g[i, ], start=i) vd } setMethod("wrap", signature(x="Spatial"), function(x) { pv <- .packVector(x) if (methods::.hasSlot(x, "data")) { pv@attributes <- x@data } pv } ) setMethod("wrap", signature(x="SpatVector"), function(x) { pv <- .packVector(x) pv@attributes <- as.data.frame(x) pv } ) setMethod("vect", signature(x="PackedSpatVector"), function(x) { p <- methods::new("SpatVector") p@ptr <- SpatVector$new() if (!is.na(x@crs)) { crs(p) <- x@crs } if (nrow(x@coordinates) == 0) { return(p) } n <- ncol(x@index) reps <- diff(c(x@index[,n], nrow(x@coordinates)+1)) i <- rep(1:nrow(x@index), reps) if (n == 2) { p@ptr$setGeometry(x@type, x@index[i,1], x@index[i,2], x@coordinates[,1], x@coordinates[,2], rep(0, nrow(x@coordinates))) } else { p@ptr$setGeometry(x@type, x@index[i,1], x@index[i,2], x@coordinates[,1], x@coordinates[,2], x@index[i,3]) } if (nrow(x@attributes) > 0) { values(p) <- x@attributes } messages(p, "pack") } ) setMethod("show", signature(object="PackedSpatVector"), function(object) { print(paste("This is a", class(object), "object. Use 'terra::vect()' to unpack it")) } ) setMethod("as.character", signature(x="SpatRaster"), function(x) { e <- as.vector(ext(x)) crs <- crs(x) crs <- ifelse(is.na(crs), ", crs=''", paste0(", crs='", crs, "'")) crs <- gsub("\n[ ]+", "", crs) nms <- paste0(", names=c('", paste(names(x), collapse="', '"), "')") paste0("rast(", "ncols=", ncol(x), ", nrows=", nrow(x), ", nlyrs=", nlyr(x), ", xmin=",e[1], ", xmax=",e[2], ", ymin=",e[3], ", ymax=",e[4], nms, crs, ")" ) } ) #eval(parse(text=as.character(s))) setMethod("wrap", signature(x="SpatRaster"), function(x) { r <- methods::new("PackedSpatRaster") r@definition <- as.character(x) r@values <- values(x) if (any(is.factor(x))) { r@attributes$levels <- levels(x) } v <- time(x) if (any(!is.na(v))) { r@attributes$time <- v } v <- units(x) if (any(!is.na(v))) { r@attributes$units <- v } v <- depth(x) if (any(!is.na(v))) { r@attributes$depth <- v } r } ) setMethod("rast", signature(x="PackedSpatRaster"), function(x) { r <- eval(parse(text=x@definition)) values(r) <- x@values if (length(x@attributes) > 0) { nms <- names(x@attributes) if (all(nms %in% c("levels", "time", "units", "depth"))) { time(r) <- x@attributes$time units(r) <- x@attributes$units levels(r) <- x@attributes$levels depth(r) <- x@attributes$depth } else { levels(r) <- x@attributes } } r } ) setMethod("show", signature(object="PackedSpatRaster"), function(object) { print(paste("This is a", class(object), "object. Use 'terra::rast()' to unpack it")) } ) terra/R/distance.R0000644000175000017500000000675714201035747013661 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : July 2019 # Version 1.0 # License GPL v3 setMethod("buffer", signature(x="SpatRaster"), function(x, width, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$buffer(width, opt) messages(x, "buffer") } ) setMethod("distance", signature(x="SpatRaster", y="missing"), function(x, y, grid=FALSE, filename="", ...) { opt <- spatOptions(filename, ...) if (grid) { if (is.lonlat(x)) { return(gridDistance(x, filename=filename, ...)) } else { x@ptr <- x@ptr$gridDistance(opt) } } else { x@ptr <- x@ptr$rastDistance(opt) } messages(x, "distance") } ) setMethod("distance", signature(x="SpatRaster", y="SpatVector"), function(x, y, filename="", ...) { opt <- spatOptions(filename, ...) if (is.lonlat(x, perhaps=TRUE)) { x@ptr <- x@ptr$vectDisdirRasterize(y@ptr, TRUE, TRUE, FALSE, FALSE, opt) } else { x@ptr <- x@ptr$vectDistanceDirect(y@ptr, opt) } messages(x, "distance") } ) mat2wide <- function(m, sym=TRUE, keep=NULL) { if (inherits(m, "dist")) { # sym must be true in this case nr <- attr(m, "Size") x <- rep(1:(nr-1), (nr-1):1) y <- unlist(sapply(2:nr, function(i) i:nr)) cbind(x,y, as.vector(m)) } else { bool <- is.logical(m) if (sym) { m[lower.tri(m)] <- NA } m <- cbind(from=rep(1:nrow(m), each=ncol(m)), to=rep(1:ncol(m), nrow(m)), value=as.vector(t(m))) m <- m[!is.na(m[,3]), , drop=FALSE] if (!is.null(keep)) { m <- m[m[,3] == keep, 1:2, drop=FALSE] } m } } setMethod("distance", signature(x="SpatVector", y="ANY"), function(x, y, sequential=FALSE, pairs=FALSE, symmetrical=TRUE) { if (!missing(y)) { error("distance", "If 'x' is a SpatVector, 'y' should be a SpatVector or missing") } if (sequential) { return( x@ptr$distance_self(sequential)) } d <- x@ptr$distance_self(sequential) messages(x, "distance") class(d) <- "dist" attr(d, "Size") <- nrow(x) attr(d, "Diag") <- FALSE attr(d, "Upper") <- FALSE attr(d, "method") <- "spatial" if (pairs) { d <- as.matrix(d) diag(d) <- NA d <- mat2wide(d, symmetrical) } d } ) setMethod("distance", signature(x="SpatVector", y="SpatVector"), function(x, y, pairwise=FALSE) { d <- x@ptr$distance_other(y@ptr, pairwise) messages(x, "distance") if (!pairwise) { d <- matrix(d, nrow=nrow(x), ncol=nrow(y), byrow=TRUE) } d } ) setMethod("distance", signature(x="matrix", y="matrix"), function(x, y, lonlat, pairwise=FALSE) { if (missing(lonlat)) { error("distance", "you must set lonlat to TRUE or FALSE") } stopifnot(ncol(x) == 2) stopifnot(ncol(y) == 2) crs <- ifelse(lonlat, "+proj=longlat +datum=WGS84", "+proj=utm +zone=1 +datum=WGS84") x <- vect(x, crs=crs) y <- vect(y, crs=crs) distance(x, y, pairwise) } ) setMethod("distance", signature(x="matrix", y="missing"), function(x, y, lonlat=NULL, sequential=FALSE) { if (is.null(lonlat)) { error("distance", "lonlat should be TRUE or FALSE") } crs <- ifelse(isTRUE(lonlat), "+proj=longlat +datum=WGS84", "+proj=utm +zone=1 +datum=WGS84") x <- vect(x, crs=crs) distance(x, sequential=sequential) } ) setMethod("direction", signature(x="SpatRaster"), function(x, from=FALSE, degrees=FALSE, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$rastDirection(from[1], degrees[1], opt) messages(x, "direction") } ) terra/R/extract.R0000644000175000017500000003017114202514436013522 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : November 2018 # Version 1.0 # License GPL v3 .big_number_warning <- function() { # this warning should be given by C warn("big number", "cell numbers larger than ", 2^.Machine$double.digits, " are approximate") } ext_from_rc <- function(x, r1, r2, c1, c2){ e <- as.vector(ext(x)) r <- res(x) c1 <- min(max(c1, 1), ncol(x)) c2 <- min(max(c2, 1), ncol(x)) if (c1 > c2) { tmp <- c1 c1 <- c2 c2 <- tmp } r1 <- min(max(r1, 1), nrow(x)) r2 <- min(max(r2, 1), nrow(x)) if (r1 > r2) { tmp <- r1 r1 <- r2 r2 <- tmp } xn <- xFromCol(x, c1) - 0.5 * r[1] xx <- xFromCol(x, c2) + 0.5 * r[1] yx <- yFromRow(x, r1) + 0.5 * r[2] yn <- yFromRow(x, r2) - 0.5 * r[2] ext(c(sort(c(xn, xx))), sort(c(yn, yx))) } setlabs <- function(x, labs) { x[ (x<1) | (x>length(labs))] <- NA x <- factor(x, levels=1:length(labs)) levels(x) <- labs x } wmean <- function(p, na.rm=FALSE) { n <- length(p) w <- p[[n]] p[[n]] <- NULL sapply(p, function(x) { stats::weighted.mean(x, w, na.rm=na.rm) }) } wsum <- function(p, na.rm=FALSE) { n <- length(p) w <- p[[n]] p[[n]] <- NULL sapply(p, function(x) { sum(x * w, na.rm=na.rm) }) } wmin <- function(p, na.rm=FALSE) { n <- length(p) p[[n]] <- NULL sapply(p, function(x) { min(x, na.rm=na.rm) }) } wmax <- function(p, na.rm=FALSE) { n <- length(p) p[[n]] <- NULL sapply(p, function(x) { max(x, na.rm=na.rm) }) } #if (!list) { #if (geomtype(y) == "points") { # e <- cbind(ID=1:length(e), matrix(unlist(e), ncol=nlyr(x), byrow=TRUE)) #} else { # e <- lapply(1:length(e), function(i) { # ee <- unlist(e[[i]]) # if (length(ee) == 0) ee <- NA # cbind(ID=i, matrix(ee, ncol=length(e[[i]]))) # }) # e <- do.call(rbind, e) #} #} extractCells <- function(x, y, method="simple", list=FALSE, factors=TRUE, cells=FALSE, xy=FALSE, layer=NULL) { method <- match.arg(tolower(method), c("simple", "bilinear")) nl <- nlyr(x) useLyr <- FALSE if (!is.null(layer) && nl > 1) { if (any(is.na(layer))) {error("extract", "argument 'layer' cannot have NAs")} stopifnot(length(layer) == length(y)) if (is.numeric(layer)) { layer <- round(layer) stopifnot(min(layer) > 0 & max(layer) <= nlyr(x)) } else { layer <- match(layer, names(x)) if (any(is.na(layer))) error("extract", "names in argument 'layer' do not match names(x)") } useLyr <- TRUE } cn <- names(x) opt <- spatOptions() if ((method == "bilinear") && (NCOL(y) > 1)) { e <- x@ptr$bilinearValues(y[,1], y[,2]) } else { if (NCOL(y) == 2) { y <- cellFromXY(x, y) } e <- x@ptr$extractCell(y-1) } if (list) { messages(x, "extract") return(e) } e <- do.call(cbind, e) cn <- names(x) nc <- nl if (cells) { cn <- c(cn, "cell") nc <- nc + 1 if (NCOL(y) == 2) { e <- cbind(e, cellFromXY(x, y)) } else { e <- cbind(e, y) } } if (xy) { cn <- c(cn, "x", "y") nc <- nc + 2 if (NCOL(y) == 1) { y <- xyFromCell(x, y) } e <- cbind(e, y) } colnames(e) <- cn if (factors) { if (method != "simple") { e <- as.data.frame(e) } else { e <- .makeDataFrame(x, e, TRUE) } } if (useLyr) { idx <- cbind(e[,1], layer[e[,1]]+1) ee <- cbind(e[,1,drop=FALSE], names(x)[idx[,2]-1], value=e[idx]) colnames(ee)[2] <- "layer" if (ncol(e) > (nl+1)) { cbind(ee, e[,(nl+1):ncol(e), drop=FALSE]) } else { ee } } else { e } } setMethod("extract", signature(x="SpatRaster", y="matrix"), function(x, y, ...) { .checkXYnames(colnames(y)) extractCells(x, y, ...) }) setMethod("extract", signature(x="SpatRaster", y="SpatVector"), function(x, y, fun=NULL, method="simple", list=FALSE, factors=TRUE, cells=FALSE, xy=FALSE, weights=FALSE, exact=FALSE, touches=is.lines(y), layer=NULL, ...) { nl <- nlyr(x) useLyr <- FALSE method <- match.arg(tolower(method), c("simple", "bilinear")) hasfun <- !is.null(fun) if (weights && exact) { exact = FALSE } if (hasfun) { cells <- FALSE xy <- FALSE if (weights || exact) { list <- TRUE fun <- .makeTextFun(fun) bad <- FALSE if (is.character(fun)) { if (!(fun %in% c("sum", "mean", "min", "max"))) { bad <- TRUE } else if (fun == "mean") { fun <- wmean } else if (fun == "sum") { fun <- wsum } else if (fun == "min") { fun <- wmin } else if (fun == "max") { fun <- wmax } } else { bad <- TRUE } if (bad) error("extract", 'if weights or exact=TRUE, "fun" must be "sum", "mean", "min", or "max"') } } if (!is.null(layer) && nl > 1) { if (any(is.na(layer))) {error("extract", "argument 'layer' cannot have NAs")} if (length(layer) == 1) { lyr_name <- layer layer <- as.character(y[[layer,drop=TRUE]]) } else { lyr_name <- "layer" stopifnot(length(layer) == nrow(y)) } if (is.numeric(layer)) { layer <- round(layer) stopifnot(min(layer) > 0 & max(layer) <= nl) } else { layer <- match(layer, names(x)) if (any(is.na(layer))) error("extract", "names in argument 'layer' do not match names(x)") } useLyr <- TRUE } #f <- function(i) if(length(i)==0) { NA } else { i } #e <- rapply(e, f, how="replace") cn <- names(x) opt <- spatOptions() if (list) { e <- x@ptr$extractVector(y@ptr, touches[1], method, isTRUE(cells[1]), isTRUE(xy[1]), isTRUE(weights[1]), isTRUE(exact[1]), opt) x <- messages(x, "extract") if (weights || exact) { if (hasfun) { e <- sapply(e, fun, ...) e <- matrix(e, nrow=nrow(y), byrow=TRUE) colnames(e) <- cn e <- cbind(ID=1:nrow(e), e) } } return(e) } e <- x@ptr$extractVectorFlat(y@ptr, touches[1], method, isTRUE(cells[1]), isTRUE(xy[1]), isTRUE(weights[1]), isTRUE(exact[1]), opt) x <- messages(x, "extract") nc <- nl if (cells) { cn <- c(cn, "cell") nc <- nc + 1 } if (weights) { cn <- c(cn, "weight") nc <- nc + 1 } else if (exact) { cn <- c(cn, "fraction") nc <- nc + 1 } if (xy) { cn <- c(cn, "x", "y") nc <- nc + 2 } geo <- geomtype(y) if (geo == "points") { ## this was? should be fixed upstream if (nc == nl) { e <- matrix(e, ncol=nc) } else { e <- matrix(e, ncol=nc, byrow=TRUE) } e <- cbind(1:nrow(e), e) if (nrow(e) > nrow(y)) { #multipoint g <- geom(y) e[,1] <- g[,1] } } else { e <- matrix(e, ncol=nc+1, byrow=TRUE) } cn <- c("ID", cn) colnames(e) <- cn if (hasfun) { fun <- match.fun(fun) e <- data.frame(e) e <- aggregate(e[,-1,drop=FALSE], e[,1,drop=FALSE], fun, ...) m <- sapply(e, NCOL) if (any(m > 1)) { e <- do.call(cbind, as.list(e)) skip <- (length(cn) - nlyr(x)) nms <- colnames(e) snms <- nms[(skip+1):length(nms)] mr <- max(m) if (!all(snms=="")) { snms <- paste0(rep(names(x), each=mr), ".", snms) } else { snms <- paste0(rep(names(x), each=mr), ".", rep(1:mr)) } snms <- c(cn[1:skip], snms) colnames(e) <- snms e <- data.frame(e) } } else if (cells) { cncell <- cn =="cell" e[, cncell] <- e[, cncell] + 1 } if (factors) { if (hasfun || method != "simple") { e <- as.data.frame(e) } else { id <- data.frame(e[,1,drop=FALSE]) e <- cbind(id, .makeDataFrame(x, e[,-1,drop=FALSE], TRUE)) } } if (useLyr) { idx <- cbind(e[,1], layer[e[,1]]+1) ee <- cbind(e[,1,drop=FALSE], names(x)[idx[,2]-1], value=e[idx]) colnames(ee)[2] <- lyr_name if (ncol(e) > (nl+1)) { e <- cbind(ee, e[,(nl+1):ncol(e), drop=FALSE]) } else { e <- ee } } e }) setMethod("[", c("SpatRaster", "SpatVector", "missing"), function(x, i, j, ... , drop=FALSE) { v <- extract(x, i) if (drop) { as.vector(v) } else { v } }) setMethod("[", c("SpatVector", "SpatVector", "missing"), function(x, i, j, ... , drop=FALSE) { r <- !relate(x, i, "disjoint") r <- which(apply(r, 1, any)) x[r, ] }) setMethod("[", c("SpatVector", "SpatExtent", "missing"), function(x, i, j, ... , drop=FALSE) { x[as.polygons(i)] }) setMethod("extract", signature(x="SpatRaster", y="data.frame"), function(x, y, ...) { if (ncol(y) != 2) { error("extract", "extract expects a 2 column data.frame of x and y coordinates") } v <- vect(y, colnames(y)) extract(x, v, ...) }) setMethod("extract", signature(x="SpatRaster", y="numeric"), function(x, y, ...) { y <- as.integer(y) y[(y < 1) | (y > ncell(x))] <- NA x[y] }) setMethod("extract", signature(x="SpatRaster", y="SpatExtent"), function(x, y, factors=TRUE, cells=FALSE, xy=FALSE) { y <- cells(x, y) if (factors) dataframe = TRUE v <- extract_cell(x, y, factors=factors) if (cells) { v$cell <- y } if (xy) { v <- cbind(v, xyFromCell(x, y)) } v } ) setMethod("[", c("SpatRaster", "missing", "missing"), function(x, i, j, ... , drop=FALSE) { values(x, mat=!drop) }) setMethod("[", c("SpatRaster", "logical", "missing"), function(x, i, j, ... , drop=FALSE) { x[which(i),, drop=drop] }) extract_cell <- function(x, cells, drop=FALSE, factors=TRUE) { e <- x@ptr$extractCell(cells-1) messages(x, "extract_cell") e <- do.call(cbind, e) colnames(e) <- names(x) .makeDataFrame(x, e, factors)[,,drop] } setMethod("[", c("SpatRaster", "numeric", "missing"), function(x, i, j, ... , drop=TRUE) { add <- any(grepl("drop", names(match.call()))) if (!drop) { if (nargs() == 3) { rc <- rowColFromCell(x, i) e <- ext_from_rc(x, min(rc[,1]), max(rc[,1]), min(rc[,2]), max(rc[,2])) } else { e <- ext_from_rc(x, min(i), max(i), 1, ncol(x)) } return(crop(x, e)) } if (nargs() > (2+add)) { i <- cellFromRowColCombine(x, i, 1:ncol(x)) } extract_cell(x, i, drop=FALSE) }) setMethod("[", c("SpatRaster", "data.frame", "missing"), function(x, i, j, ... , drop=TRUE) { if (ncol(i) == 1) { i <- i[,1] } else if (ncol(i) == 2) { i <- cellFromXY(x, i) } else { error(" [", "cannot extract values with this data.frame") } `[`(x, i, drop=drop) }) setMethod("[", c("SpatRaster", "matrix", "missing"), function(x, i, j, ... , drop=TRUE) { if (ncol(i) == 1) { i <- i[,1] } else if ((nrow(i) == 1) && (ncol(i) != 2)) { i <- i[1,] } else if (ncol(i) == 2) { i <- cellFromXY(x, i) } else { error(" [", "cannot extract values with a ` of these dimensions") } `[`(x, i, drop=drop) }) setMethod("[", c("SpatRaster", "missing", "numeric"), function(x, i, j, ... , drop=TRUE) { if (!drop) { e <- ext_from_rc(x, 1, nrow(x), min(j), max(j)) return(crop(x, e)) } i <- cellFromRowColCombine(x, 1:nrow(x), j) extract_cell(x, i, drop=FALSE) }) setMethod("[", c("SpatRaster", "numeric", "numeric"), function(x, i, j, ..., drop=TRUE) { if (!drop) { e <- ext_from_rc(x, min(i), max(i), min(j), max(j)) return(crop(x, e)) } i <- cellFromRowColCombine(x, i, j) extract_cell(x, i, drop=FALSE) }) setMethod("[", c("SpatRaster", "SpatRaster", "missing"), function(x, i, j, ..., drop=TRUE) { if (!compareGeom(x, i, crs=FALSE, stopOnError=FALSE)) { return (x[ext(i), drop=drop]) } if (drop) { if (is.bool(i)) { i <- as.logical(values(i)) } else { i <- !is.na(values(i)) } values(x)[i,] } else { if (is.bool(i)) { mask(x, i, maskvalues=FALSE) } else { mask(x, i) } } }) setMethod("[", c("SpatRaster", "SpatExtent", "missing"), function(x, i, j, ..., drop=FALSE) { x <- crop(x, i) if (drop) { values(x) } else { x } }) setMethod("extract", c("SpatVector", "SpatVector"), function(x, y, ...) { #r <- relate(y, x, "within") #e <- apply(r, 1, which) r <- relate(x, y, "covers") e <- apply(r, 2, which) if (length(e) == 0) { e <- list(e) } if (is.list(e)) { e <- lapply(1:length(e), function(i) { if (length(e[[i]]) == 0) { cbind(i, NA) } else { cbind(i, e[[i]]) } }) e <- do.call(rbind, e) } else { e <- cbind(1:nrow(y), e) } if (ncol(x) > 0) { d <- as.data.frame(x) e <- data.frame(id.y=e[,1], d[e[,2], ,drop=FALSE]) rownames(e) <- NULL } else { colnames(e) <- c("id.y", "id.x") } e }) terra/R/connect.R0000644000175000017500000000305014201035747013477 0ustar nileshnilesh get_groups <- function(x, y) { j <- 1 outx <- outy <- list() for (i in 1:length(x)) { if (is.na(x[i])) next gx <- na.omit(x[x[i] == x] ) gy <- y[x %in% gx] nx <- ny <- 0 while(TRUE) { if (nx == length(gx)) break ny <- length(gy) nx <- length(gx) if ((ny == length(y) || (nx == length(x)))) break ux <- unique( x[y %in% gy] ) gy <- y[x %in% ux] gx <- x[y %in% gy] } x[x %in% gx] <- NA y[y %in% gy] <- NA outx[[j]] <- gx outy[[j]] <- gy j <- j + 1 } list(outx, outy) } connect_dateline <- function(x) { east <- west <- c() for (i in 1:nrow(x)) { e <- ext(x[i,]) if (xmin(e) <= -180) { west <- c(west, i) } else if (xmax(e) >= 180) { east <- c(east, i) } } if ((length(east) == 0) || (length(west) == 0)) { return(x) } xx <- shift(x[west,], 360, 0) yy <- x[east, ] #zz <- x[-c(east, west), ] px <- py <- c() hasDF <- ncol(x) > 0 for (i in 1:nrow(xx)) { for (j in 1:nrow(yy)) { if (hasDF) { if (all(as.data.frame(xx[i,]) != as.data.frame(yy[j,]))) { next } } if (relate(xx[i,], yy[j,], "touches")) { px <- c(px, i) py <- c(py, j) } } } if ((length(px) == 0)) { return(x) } px <- west[px] py <- east[py] groups <- get_groups(px, py) xg <- groups[[1]] yg <- groups[[2]] vvv <- list() for (i in 1:length(xg)) { vvv[[i]] <- aggregate(x[unique(c(xg[[i]], yg[[i]])), ], dissolve=TRUE) } out <- x[-(unique(unlist(groups))), ] out <- c(vvv, out) do.call(rbind, out) } terra/R/arith.R0000644000175000017500000000175214201035747013164 0ustar nileshnilesh # setMethod("arith", signature(x="SpatRaster"), ## not exported arith <- function(x, fun, ..., filename="", overwrite=FALSE, wopt=list()) { out <- rast(x) nc <- ncol(x) readStart(x) on.exit(readStop(x)) # # test the shape of the output by testing with one row v <- readValues(x, round(0.5*nrow(x)), 1, 1, nc, mat=TRUE) r <- try(fun(as.vector(v), ...)) if (inherits(r, "try-error")) { error("arith", "'fun' is not valid") } if (!is.vector(r)) { error("arith", "'fun' does not return a vector") } if (!(is.numeric(r) | is.logical(r))) { error("arith", "'fun' does not return a numeric vector") } if (length(r) != length(v)) { error("arith", "'fun' does not return the same number of values as the input") } b <- writeStart(out, filename, overwrite, wopt=wopt) for (i in 1:b$n) { v <- readValues(x, b$row[i], b$nrows[i], 1, nc, TRUE) v <- fun(as.vector(v), ...) writeValues(out, v, b$row[i], b$nrows[i]) } writeStop(out) } # ) terra/R/messages.R0000644000175000017500000000323014201035747013655 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : October 2018 # Version 1.0 # License GPL v3 error <- function(f, emsg="", ...) { stop("[", f, "] ", emsg, ..., call.=FALSE) } warn <- function(f, wmsg="", ...) { warning("[", f, "] ", wmsg, ..., call.=FALSE) } messages <- function(x, f="") { if (methods::.hasSlot(x, "ptr")) { if (x@ptr$has_warning()) { warn(f, paste(x@ptr$getWarnings(), collapse="\n")) } if (x@ptr$has_error()) { error(f, x@ptr$getError()) } return(x) } else { if (x$has_warning()) { warn(f, paste(x$getWarnings(), collapse="\n")) } if (x$has_error()) { error(f, x$getError()) } return(x) } } mem_info <- function(x, n=1) { n <- max(0,n) opt <- spatOptions() opt$ncopies = n; v <- x@ptr$mem_needs(opt) memmax <- opt$memmax #if (print) { gb <- 1024^3 / 8 # cat("\n------------------------") cat("\nMemory (GB) ") cat("\n------------------------") if (memmax > 0) { cat(paste("\navailable :", round(v[2] / gb, 2), "(memmax)")) } else { cat(paste("\navailable :", round(v[2] / gb, 2))) } cat(paste0("\nallowed (", round(100* v[3]) , "%) : ", round(v[3] * v[2] / gb, 2))) cat(paste0("\nneeded (n=", n, ") ", ifelse(n<10, " : ", ": "), round(v[1] / gb, 2))) cat("\n------------------------") cat(paste("\nproc in memory :", round(v[5]) != 0)) cat(paste("\nnr chunks :", ceiling(nrow(x)/v[4]))) cat("\n------------------------\n") #} names(v) <- c("needed", "available", "memfrac", "chunksize") } free_RAM <- function() { opt <- spatOptions() x <- rast() v <- x@ptr$mem_needs(opt) v[2] / 128 } terra/R/replace.R0000644000175000017500000001275114201035747013471 0ustar nileshnilesh# Author: Robert J. Hijmans # Date: October 2018 # Version 1.0 # License GPL v3 setMethod("$<-", "SpatRaster", function(x, name, value) { if (inherits(value, "SpatRaster")) { value <- value[[1]] names(value) <- name } else if (!is.null(value)) { y <- rast(x, nlyrs=1) test <- try(values(y) <- value, silent=TRUE) if (inherits(test, "try-error")) { error("$<-,SpatRaster", "the replacement value is not valid") } value <- y names(value) <- name } i <- which(name == names(x))[1] if (is.na(i)) { c(x, value) } else if (nlyr(x) == 1) { value$deepcopy() } else if (i == 1) { c(value, x[[2:nlyr(x)]]) } else if (i == nlyr(x)) { c(x[[1:(nlyr(x)-1)]], value) } else { c(x[[1:(i-1)]], value, x[[(i+1):nlyr(x)]]) } } ) setReplaceMethod("[[", c("SpatRaster", "character", "missing"), function(x, i, j, value) { if (inherits(value, "SpatRaster")) { if (nlyr(value) != length(i)) { error(" [[,SpatRaster", "length of names must be equal to the number of layers") } names(value) <- i } else if (length(i) > 1) { if (NCOL(value) > 1) { value <- as.list(data.frame(value)) } else { stopifnot(length(i) == length(value)) } } else if (!is.list(value)) { value <- list(value) } for (k in 1:length(i)) { eval(parse(text = paste0("x$", i[k], " <- value[[k]]"))) } x } ) setReplaceMethod("[[", c("SpatRaster", "numeric", "missing"), function(x, i, j, value) { if (nlyr(value) != length(i)) { error(" [[,SpatRaster,numeric", "length of indices must be equal to the number of layers") } if (any(i<1) | any(i > nlyr(x))) { error(" [[,SpatRaster,numeric", "indices must be between 1 and the number of layers") } for (k in 1:length(i)) { if (i[k] == 1) { x <- c(value[[k]], x[[2:nlyr(x)]]) } else if (i[k] == nlyr(x)) { x <- c(x[[1:(nlyr(x)-1)]], value[[k]]) } else { x <- c(x[[1:(i[k]-1)]], value[[k]], x[[(i[k]+1):nlyr(x)]]) } } x } ) setReplaceMethod("[", c("SpatRaster", "missing", "missing"), function(x, i, j, value) { nl <- nlyr(x) if (is.matrix(value)) { if (all(dim(value) == c(ncell(x), nl))) { x <- try( setValues(x, value, TRUE, TRUE) ) } else { error(" [,SpatRaster","dimensions of the matrix do not match the SpatRaster") } } else { v <- try( matrix(nrow=ncell(x), ncol=nl) ) if (! inherits(x, "try-error")) { v[] <- value x <- try( setValues(x, v, TRUE, TRUE) ) } } if (inherits(x, "try-error")) { error(" [,SpatRaster", "cannot set values") } return(x) } ) setReplaceMethod("[", c("SpatRaster","numeric", "missing"), function(x, i, j, value) { theCall <- sys.call(-1) narg <- length(theCall)-length(match.call(call=sys.call(-1))) if (narg > 0) { # row i <- cellFromRowColCombine(x, i, 1:ncol(x)) } bylyr = FALSE if (!is.null(dim(value))) { #x@ptr <- x@ptr$replaceValues(i, value, ncol(value)) stopifnot(ncol(value) == nlyr(x)) bylyr = TRUE if (inherits(value, "data.frame")) { value <- as.matrix(value) } value <- as.vector(value) } x@ptr <- x@ptr$deepcopy() if (!x@ptr$replaceCellValues(i-1, value, bylyr, spatOptions())) { messages(x) } else { x } } ) setMethod("set.values", signature(x="SpatRaster"), function(x, cells, values) { if (missing(cells) && missing(values)) { x@ptr$readAll() return(invisible(TRUE)); } bylyr = FALSE if (!is.null(dim(values))) { stopifnot(ncol(values) == nlyr(x)) bylyr = TRUE if (inherits(values, "data.frame")) { values <- as.matrix(values) } values <- as.vector(values) } if (!x@ptr$replaceCellValues(cells-1, values, bylyr, spatOptions())) { messages(x) } else { invisible(TRUE) } } ) setReplaceMethod("[", c("SpatRaster", "numeric", "numeric"), function(x, i, j, value) { i <- cellFromRowColCombine(x, i, j) x[i] <- value x } ) setReplaceMethod("[", c("SpatRaster","missing", "numeric"), function(x, i, j, value) { i <- cellFromRowColCombine(x, 1:nrow(x), j) x[i] <- value x } ) setReplaceMethod("[", c("SpatRaster", "logical", "missing"), function(x, i, j, value) { i <- which(rep_len(i, ncell(x))) x[i] <- value x } ) setReplaceMethod("[", c("SpatRaster", "SpatRaster", "ANY"), function(x, i, j, value) { theCall <- sys.call(-1) narg <- length(theCall)-length(match.call(call=sys.call(-1))) if (narg > 0) { # row error(" [,SpatRaster,SpatRaster", "you cannot use a SpatRaster as a row index") } if (inherits(value, "SpatRaster")) { x <- mask(x, i, maskvalues=TRUE) cover(x, value) } else { if (NCOL(value) > 1) { error(" [", "cannot use a data.frame with multiple columns") } value <- unlist(value) if (length(value) == 1) { mask(x, i, maskvalues=TRUE, updatevalue=value[1]) } else { i <- as.logical(values(i)) i[is.na(i)] <- TRUE i <- which(i) x[i] <- value x } } } ) setReplaceMethod("[", c("SpatRaster", "SpatVector", "missing"), function(x, i, j, value) { theCall <- sys.call(-1) narg <- length(theCall)-length(match.call(call=sys.call(-1))) if (narg > 0) { # row error(" [,SpatRaster,SpatVector", "you cannot use a SpatVector as a row index") } if (length(value) > 1) { value <- rep_len(value, length.out=length(x)) } rasterize(i, x, field=value, update=TRUE) } ) terra/R/generics.R0000644000175000017500000005454514201604516013660 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : October 2018 # Version 1.0 # License GPL v3 setMethod("all.equal", signature(target="SpatRaster", current="SpatRaster"), function(target, current, maxcell=10000, ...) { first <- all.equal.default(target, current) if (isTRUE(first)) { if (hasValues(target)) { if (ncell(x) > maxcell) { s <- round(100 * maxcell / ncell(x)) warn("all.equal", paste0("using a sample of ", s, "% of the cells")) } vt <- spatSample(target, maxcell, "regular") ct <- spatSample(current, maxcell, "regular") all.equal(vt, ct, ...) } else { first } } else { first } } ) setMethod("weighted.mean", signature(x="SpatRaster", w="numeric"), function(x, w, na.rm=FALSE, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$wmean_vect(w, na.rm, opt) messages(x, "weighted.mean") } ) setMethod("weighted.mean", signature(x="SpatRaster", w="SpatRaster"), function(x, w, na.rm=FALSE, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <-x@ptr$wmean_rast(w@ptr, na.rm, opt) messages(x, "weighted.mean") } ) setMethod("patches", signature(x="SpatRaster"), function(x, directions=4, zeroAsNA=FALSE, allowGaps=TRUE, filename="", ...) { if (allowGaps) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$patches(directions[1], zeroAsNA[1], opt) messages(x, "patches") } else { opt <- spatOptions() x@ptr <- x@ptr$patches(directions[1], zeroAsNA[1], opt) x <- messages(x, "patches") f <- freq(x) fr <- cbind(f[,2], 1:nrow(f)) fr <- fr[fr[,1] != fr[,2], ,drop=FALSE] if (nrow(fr) > 0) { x <- classify(x, fr, filename=filename, ...) } else if (filename != "") { x <- writeRaster(x, filename=filename, ...) } x } } ) setMethod("origin", signature(x="SpatRaster"), function(x) { x@ptr$origin } ) setMethod("origin<-", signature("SpatRaster"), function(x, value) { value <- rep(value, length.out=2) dif <- value - origin(x) res <- res(x) dif[1] <- dif[1] %% res[1] dif[2] <- dif[2] %% res[2] for (i in 1:2) { if (dif[i] < 0) { if ((dif[i] + res[i]) < abs(dif[i])) { dif[i] <- dif[i] + res[i] } } else { if (abs(dif[i] - res[i]) < dif[i]) { dif[i] <- dif[i] - res[i] } } } e <- as.vector(ext(x)) e["xmin"] <- e["xmin"] + dif[1] e["xmax"] <- e["xmax"] + dif[1] e["ymin"] <- e["ymin"] + dif[2] e["ymax"] <- e["ymax"] + dif[2] ext(x) <- e return(x) } ) setMethod("align", signature(x="SpatExtent", y="SpatRaster"), function(x, y, snap="near") { x@ptr <- y@ptr$align(x@ptr, tolower(snap)) #messages(x, "align") x } ) setMethod("align", signature(x="SpatExtent", y="numeric"), function(x, y) { x@ptr <- x@ptr$align(y, "") x } ) setMethod("cellSize", signature(x="SpatRaster"), function(x, mask=TRUE, unit="m", transform=TRUE, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$rst_area(mask, unit, transform, opt) messages(x, "cellSize") } ) setMethod ("expanse", "SpatRaster", function(x, unit="m", transform=TRUE) { byvalue = FALSE opt <- spatOptions() if (byvalue) { v <- x@ptr$area_by_value(opt) x <- messages(x, "expanse") v <- lapply(1:length(v), function(i) cbind(i, matrix(v[[i]], ncol=2))) v <- do.call(rbind, v) colnames(v) <- c("layer", "value", "area") } else { v <- x@ptr$sum_area(unit, transform, opt) x <- messages(x, "expanse") } return(v) } ) setMethod("atan2", signature(y="SpatRaster", x="SpatRaster"), function(y, x) { opt <- spatOptions(filename="", overwrite=TRUE) y@ptr <- y@ptr$atan2(x@ptr, opt) messages(y, "atan2") } ) setMethod("atan_2", signature(y="SpatRaster", x="SpatRaster"), function(y, x, filename="", ...) { opt <- spatOptions(filename=filename, ...) y@ptr <- y@ptr$atan2(x@ptr, opt) messages(y, "atan_2") } ) setMethod("boundaries", signature(x="SpatRaster"), function(x, classes=FALSE, inner=TRUE, directions=8, falseval=0, filename="", ...) { opt <- spatOptions(filename, ...) type <- ifelse(inner[1], "inner", "outer") x@ptr <- x@ptr$boundaries(classes[1], type, directions[1], falseval[1], opt) messages(x, "boundaries") } ) .collapseSources <- function(x) { x@ptr <- x@ptr$collapse_sources() messages(x, "tighten") } setMethod("deepcopy", signature("SpatRaster"), function(x) { x@ptr <- x@ptr$deepcopy() x } ) setMethod("split", signature(x="SpatRaster"), function(x, f) { stopifnot(length(f) == nlyr(x)) stopifnot(!any(is.na(f))) u <- unique(f) lapply(u, function(i) x[[f==i]]) } ) setMethod("add<-", signature("SpatRaster", "SpatRaster"), function(x, value) { if (x@ptr$same(value@ptr)) { x@ptr <- x@ptr$deepcopy() } opt <- spatOptions() x@ptr$addSource(value@ptr, FALSE, opt) messages(x, "add") } ) setMethod("tighten", signature("SpatRaster"), function(x) { x@ptr <- x@ptr$collapse_sources() messages(x, "tighten") } ) setMethod("tighten", signature("SpatRasterDataset"), function(x) { y <- new("SpatRaster") y@ptr <- x@ptr$collapse() messages(y, "tighten") } ) #setMethod("c", signature(x="SpatRaster"), # function(x, ...) { # s <- sds(list(x, ...)) # x@ptr <- s@ptr$collapse() # x <- messages(x, "c") # try( x@ptr <- x@ptr$collapse_sources() ) # messages(x, "c") # } #) #cbind.SpatVector <- function(x, y, ...) { # if (inherits(y, "SpatVector")) { # y <- y@ptr$df # } else { # stopifnot(inherits(y, "data.frame")) # y <- terra:::.makeSpatDF(y) # } # x@ptr <- x@ptr$cbind(y) # messages(x, "cbind") #} cbind.SpatVector <- function(x, y, ...) { dots <- list(y, ...) for (y in dots) { if (inherits(y, "SpatVector")) { y <- y@ptr$df } else { stopifnot(inherits(y, "data.frame")) y <- .makeSpatDF(y) } x@ptr <- x@ptr$cbind(y) x <- messages(x, "cbind") } x } rbind.SpatVector <- function(x, y, ...) { skipped <- FALSE stopifnot(inherits(y, "SpatVector")) x@ptr <- x@ptr$rbind(y@ptr, FALSE) x <- messages(x, "rbind") dots <- list(...) if (!is.null(dots)) { for (y in dots) { stopifnot(inherits(y, "SpatVector")) x@ptr <- x@ptr$rbind(y@ptr, FALSE) x <- messages(x, "rbind") } } x } setMethod("c", signature(x="SpatRaster"), function(x, ..., warn=TRUE) { skips <- 0 hv <- hasValues(x) dots <- list(...) x@ptr <- x@ptr$deepcopy() opt <- spatOptions() for (i in dots) { if (inherits(i, "SpatRaster")) { x@ptr$addSource(i@ptr, warn, opt) if (x@ptr$messages$has_error) { messages(x, "c") return() } } else { skips = skips + 1 } } if (skips > 0) warn("c,SpatRaster", paste("skipped", skips, "object(s) that are not SpatRaster")) messages(x, "c") x } ) setMethod("rep", signature(x="SpatRaster"), function(x, ...) { i <- rep(1:nlyr(x), ...) x[[i]] } ) setMethod("clamp", signature(x="SpatRaster"), function(x, lower=-Inf, upper=Inf, values=TRUE, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$clamp(lower, upper, values[1], opt) messages(x, "clamp") } ) setMethod("clamp", signature(x="numeric"), function(x, lower=-Inf, upper=Inf, values=TRUE, ...) { stopifnot(lower <= upper) if (values) { x[x < lower] <- lower x[x > upper] <- upper } else { x[x < lower] <- NA x[x > upper] <- NA } x } ) setMethod("classify", signature(x="SpatRaster"), function(x, rcl, include.lowest=FALSE, right=TRUE, othersNA=FALSE, brackets=TRUE, filename="", ...) { bylayer = FALSE if (is.data.frame(rcl)) { rcl <- as.matrix(rcl) } right <- ifelse(is.na(right), 2, ifelse(isTRUE(right), 1, 0)) include.lowest <- as.logical(include.lowest[1]) opt <- spatOptions(filename, ...) x@ptr <- x@ptr$classify(as.vector(rcl), NCOL(rcl), right, include.lowest, othersNA[1], bylayer[1], brackets[1], opt) messages(x, "classify") } ) setMethod("subst", signature(x="SpatRaster"), function(x, from, to, filename="", ...) { opt <- spatOptions(filename, ...) if (inherits(to, "data.frame")) { to <- as.matrix(to) } if (inherits(to, "matrix")) { opt$names = colnames(to) x@ptr <- x@ptr$replaceValues(from, to, ncol(to), opt) } else { x@ptr <- x@ptr$replaceValues(from, to, -1, opt) } messages(x, "subst") } ) .getExt <- function(y, method="crop") { if (!inherits(y, "SpatExtent")) { e <- try(ext(y), silent=TRUE) if (class(e) == "try-error") { e <- try(ext(vect(y)), silent=TRUE) if (class(e) == "try-error") { error(method, "cannot get a SpatExtent from y") } } y <- e } y } setMethod("crop", signature(x="SpatRaster", y="ANY"), function(x, y, snap="near", mask=FALSE, filename="", ...) { opt <- spatOptions(filename, ...) if (mask && inherits(y, "SpatVector")) { x@ptr <- x@ptr$crop_mask(y@ptr, snap[1], opt) } else { y <- .getExt(y, method="crop") x@ptr <- x@ptr$crop(y@ptr, snap[1], opt) } messages(x, "crop") } ) setMethod("crop", signature(x="SpatRasterDataset", y="ANY"), function(x, y, snap="near", filename="", ...) { if (all(filename != "")) { ext <- tools::file_ext(filename) filename <- tools::file_path_sans_ext(filename) filename <- paste0(make.unique(filename, sep="_"), ext) } opt <- spatOptions(filename, ...) y <- .getExt(y, method="crop") x@ptr <- x@ptr$crop(y@ptr, snap[1], opt) messages(x, "crop") } ) setMethod("selectRange", signature(x="SpatRaster"), function(x, y, z=1, repint=0, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$selRange(y@ptr, z, repint, opt) messages(x, "selectRange") } ) setMethod("cover", signature(x="SpatRaster", y="SpatRaster"), function(x, y, values=NA, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$cover(y@ptr, values, opt) messages(x, "cover") } ) setMethod("diff", signature(x="SpatRaster"), function(x, lag=1, filename="", ...) { n <- nlyr(x) lag <- round(lag) if ((lag < 1) | (lag >= n)) { error("diff", "lag must be > 0 and < nlyr(x)") } y <- x[[-((n-lag+1):n)]] x <- x[[-(1:lag)]] opt <- spatOptions(filename, ...) x@ptr <- x@ptr$arith_rast(y@ptr, "-", opt) messages(x, "diff") } ) setMethod("disagg", signature(x="SpatRaster"), function(x, fact, method="near", filename="", ...) { stopifnot(method %in% c("near", "bilinear")) if (method == "bilinear") { y <- disagg(rast(x), fact) r <- resample(x, y, "bilinear", filename=filename, ...) return(r) } opt <- spatOptions(filename, ...) x@ptr <- x@ptr$disaggregate(fact, opt) messages(x, "disagg") } ) setMethod("flip", signature(x="SpatRaster"), function(x, direction="vertical", filename="", ...) { d <- match.arg(direction, c("vertical", "horizontal")) opt <- spatOptions(filename, ...) x@ptr <- x@ptr$flip(d == "vertical", opt) messages(x, "flip") } ) setMethod("freq", signature(x="SpatRaster"), function(x, digits=0, value=NULL, bylayer=TRUE, usenames=FALSE) { opt <- spatOptions() if (!bylayer) usenames <- FALSE if (!is.null(value)) { value <- unique(value) if (length(value) > 1) { error("freq", "value must have a length of one") } if (is.character(value)) { value <- value[value != ""] if (length(value) == 0) { error("freq", "no valid value") } ff <- is.factor(x) if (!any(ff)) { error("freq", "a character value is only meaningful for categorical rasters") } f <- freq(x[[ff]]) if (usenames) { f$layer <- names(x)[f$layer] } f <- f[f$label == value,] return(f) } if (is.na(digits)) { v <- x@ptr$count(value, bylayer[1], FALSE, 0, opt) } else { v <- x@ptr$count(value, bylayer[1], TRUE, digits, opt) value <- round(value, digits) } if (bylayer) { v <- cbind(layer=1:nlyr(x), value=value, count=v) } else { v <- cbind(value=value, count=v) } } else { if (is.na(digits)) { v <- x@ptr$freq(bylayer[1], FALSE, 0, opt) } else { v <- x@ptr$freq(bylayer[1], TRUE, digits, opt) } if (bylayer) { v <- lapply(1:length(v), function(i) cbind(i, matrix(v[[i]], ncol=2))) v <- do.call(rbind, v) colnames(v) <- c("layer", "value", "count") } else { v <- matrix(v[[1]], ncol=2, dimnames=list(NULL, c("value", "count"))) } if (bylayer | (nlyr(x) == 1)) { ff <- is.factor(x) if (any(ff)) { cgs <- cats(x) v <- data.frame(v) for (f in which(ff)) { cg <- cgs[[f]] j <- which(v[,1] == f) i <- match(v[j,2], cg[,1]) act <- activeCat(x, f) + 1 if (!inherits(cg[[act]], "numeric")) { v[j, 2] <- as.character(factor(cg[i, act], levels=unique(cg[[act]]))) } else { v[j, 2] <- cg[i, act] } } } } } if (usenames) { v <- as.data.frame(v) v$layer <- names(x)[v$layer] } v } ) setMethod("mask", signature(x="SpatRaster", mask="SpatRaster"), function(x, mask, inverse=FALSE, maskvalues=NA, updatevalue=NA, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$mask_raster(mask@ptr, inverse[1], maskvalues, updatevalue[1], opt) messages(x, "mask") } ) setMethod("mask", signature(x="SpatRaster", mask="SpatVector"), function(x, mask, inverse=FALSE, updatevalue=NA, touches=TRUE, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$mask_vector(mask@ptr, inverse[1], updatevalue[1], touches[1], opt) messages(x, "mask") } ) setMethod("project", signature(x="SpatRaster"), function(x, y, method, mask=FALSE, align=FALSE, gdal=TRUE, filename="", ...) { if (missing(method)) { if (is.factor(x)[1] || isTRUE(x@ptr$rgb)) { method <- "near" } else { method <- "bilinear" } } else { method <- method[1] } if (method == "ngb") { method <- "near" warn("project", "argument 'method=ngb' is deprecated, it should be 'method=near'") } opt <- spatOptions(filename, ...) if (inherits(y, "SpatRaster")) { if (gdal) { x@ptr <- x@ptr$warp(y@ptr, "", method, mask[1], align[1], opt) } else { if (align) { y <- project(rast(x), y, align=TRUE) } x@ptr <- x@ptr$resample(y@ptr, method, mask[1], TRUE, opt) } } else { if (inherits(y, "SpatRaster")) { y <- crs(y) } else if (!is.character(y)) { warn("project,SpatRaster", "crs should be a character value") y <- as.character(crs(y)) } if (gdal) { x@ptr <- x@ptr$warp(SpatRaster$new(), y, method, mask, FALSE, opt) } else { y <- project(rast(x), y) x@ptr <- x@ptr$resample(y@ptr, method, mask[1], TRUE, opt) } } messages(x, "project") } ) setMethod("project", signature(x="SpatVector"), function(x, y) { if (!is.character(y)) { y <- crs(y) } x@ptr <- x@ptr$project(y) messages(x, "project") } ) setMethod("quantile", signature(x="SpatRaster"), function(x, probs=seq(0, 1, 0.25), na.rm=FALSE, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$quantile(probs, na.rm[1], opt) messages(x, "quantile") } ) setMethod("quantile", signature(x="SpatVector"), function(x, probs=seq(0, 1, 0.25), ...) { x <- values(x) cls <- sapply(x, class) i <- cls != "character" if (!any(i)) error("quantile", "no numeric variables") x <- x[, i, drop=FALSE] apply(x, 2, function(i) quantile(i, probs=probs, ...)) } ) setMethod("rectify", signature(x="SpatRaster"), function(x, method="bilinear", aoi=NULL, snap=TRUE, filename="", ...) { opt <- spatOptions(filename, ...) if (!is.null(aoi)) { if (inherits(aoi, "SpatExtent")) { aoi <- rast(aoi) useaoi <- 1 } else if (inherits(aoi, "SpatRaster")) { aoi <- rast(aoi) useaoi <- 2 } else { error("rectify", "ext must be a SpatExtent or SpatRaster") } } else { aoi <- rast() useaoi <- 0 } snap <- as.logical(snap) x@ptr <- x@ptr$rectify(method, aoi@ptr, useaoi, snap, opt) messages(x, "rectify") } ) setMethod("resample", signature(x="SpatRaster", y="SpatRaster"), function(x, y, method, filename="", ...) { if (missing(method)) { method <- ifelse(is.factor(x)[1], "near", "bilinear") } if (method == "ngb") { method <- "near" warn("resample", "argument 'method=ngb' is deprecated, it should be 'method=near'") } opt <- spatOptions(filename, ...) # if (gdal) { x@ptr <- x@ptr$warp(y@ptr, "", method, FALSE, FALSE, opt) # } else { # x@ptr <- x@ptr$resample(y@ptr, method, FALSE, TRUE, opt) # } messages(x, "resample") } ) setMethod("impose", signature(x="SpatRasterCollection"), function(x, y, filename="", ...) { stopifnot(inherits(y, "SpatRaster")) opt <- spatOptions(filename, ...) r <- rast() r@ptr <- x@ptr$morph(y@ptr, opt) messages(r, "impose") } ) setMethod("rev", signature(x="SpatRaster"), function(x) { opt <- spatOptions("", FALSE, list()) x@ptr <- x@ptr$reverse(opt) messages(x, "rev") } ) setMethod("rotate", signature(x="SpatRaster"), function(x, left=TRUE, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$rotate(left, opt) messages(x, "rotate") } ) setMethod("segregate", signature(x="SpatRaster"), function(x, classes=NULL, keep=FALSE, other=0, filename="", ...) { opt <- spatOptions(filename, ...) if (is.null(classes)) classes <- 1[0] x@ptr <- x@ptr$separate(classes, keep, other, opt) messages(x, "segregate") } ) setMethod("shift", signature(x="SpatRaster"), function(x, dx=0, dy=0, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$shift(dx, dy, opt) messages(x, "shift") } ) setMethod("shift", signature(x="SpatExtent"), function(x, dx=0, dy=0) { s <- c(dx[1], dx[1], dy[1], dy[1]) ext(as.vector(x) + s) } ) setMethod("shift", signature(x="SpatVector"), function(x, dx=0, dy=0) { x@ptr <- x@ptr$shift(dx, dy) messages(x, "shift") } ) setMethod("rescale", signature(x="SpatRaster"), function(x, fx=0.5, fy=fx, x0, y0) { stopifnot(fx > 0) stopifnot(fy > 0) e <- as.vector(ext(x)) if (missing(x0)) { x0 <- mean(e[1:2]) } if (missing(y0)) { y0 <- mean(e[3:4]) } ex = x0 + fx * (e[1:2] - x0); ey = y0 + fy * (e[3:4] - y0); x@ptr <- x@ptr$deepcopy() ext(x) <- ext(c(ex, ey)) messages(x, "rescale") } ) setMethod("rescale", signature(x="SpatVector"), function(x, fx=0.5, fy=fx, x0, y0) { stopifnot(fx > 0) stopifnot(fy > 0) e <- as.vector(ext(x)) if (missing(x0)) { x0 <- mean(e[1:2]) } if (missing(y0)) { y0 <- mean(e[3:4]) } x@ptr <- x@ptr$rescale(fx, fy, x0[1], y0[1]) messages(x, "rescale") } ) setMethod("scale", signature(x="SpatRaster"), function(x, center=TRUE, scale=TRUE) { opt <- spatOptions() if (is.logical(center)) { docenter = center[1]; center = 1[0] } else { docenter = TRUE } if (is.logical(scale)) { doscale = scale[1] scale = 1[0] } else { doscale = TRUE; } x@ptr <- x@ptr$scale(center, docenter, scale, doscale, opt) messages(x, "scale") } ) setMethod("stretch", signature(x="SpatRaster"), function(x, minv=0, maxv=255, minq=0, maxq=1, smin=NA, smax=NA, histeq=FALSE, scale=1, filename="", ...) { opt <- spatOptions(filename, ...) if (histeq) { eqStretch <- function(x){ ecdfun <- stats::ecdf(x)(x) ecdfun(x) } setValues(x, apply(values(x), 2, function(i) stats::ecdf(i)(i))) * scale } else { x@ptr <- x@ptr$stretch(minv, maxv, minq, maxq, smin, smax, opt) messages(x, "stretch") } } ) setMethod("summary", signature(object="SpatRaster"), function(object, size=100000, warn=TRUE, ...) { if (!hasValues(object)) { warn("summary", "SpatRaster has no values") return(invisible()) } if (warn && (ncell(object) > size)) { warn("summary", "used a sample") } s <- spatSample(object, size, method="regular") summary(s, ...) } ) setMethod("summary", signature(object="SpatVector"), function(object, ...) { summary(as.data.frame(object), ...) } ) setMethod("t", signature(x="SpatRaster"), function(x) { opt <- spatOptions() x@ptr <- x@ptr$transpose(opt) messages(x, "t") } ) setMethod("t", signature(x="SpatVector"), function(x) { x@ptr <- x@ptr$transpose() messages(x, "t") } ) setMethod("terrain", signature(x="SpatRaster"), function(x, v="slope", neighbors=8, unit="degrees", filename="", ...) { unit <- match.arg(unit, c("degrees", "radians")) opt <- spatOptions(filename, ...) seed <- ifelse("flowdir" %in% v, .seed(), 0) x@ptr <- x@ptr$terrain(v, neighbors[1], unit=="degrees", seed, opt) messages(x, "terrain") } ) setMethod("trim", signature(x="SpatRaster"), function(x, padding=0, value=NA, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$trim(value[1], padding[1], opt) messages(x, "trim") } ) setMethod("trans", signature(x="SpatRaster"), function(x, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$transpose(opt) messages(x, "trans") } ) setMethod("unique", signature(x="SpatRaster", incomparables="ANY"), function(x, incomparables=FALSE) { opt <- spatOptions() u <- x@ptr$unique(incomparables, opt) isfact <- is.factor(x) if (any(isfact)) { ff <- which(isfact) levs <- levels(x) for (f in ff) { lvs <- levs[[f]] u[[f]] = factor(u[[f]], levels=(1:length(lvs))-1) levels(u[[f]]) = levs[[f]] } } if (!incomparables) { if (!length(u)) return(u) u <- do.call(data.frame, u) colnames(u) <- names(x) } u } ) setMethod("unique", signature(x="SpatVector", incomparables="ANY"), function(x, incomparables=FALSE, ...) { u <- unique(as.data.frame(x, geom="WKT"), incomparables=incomparables, ...) v <- vect(u, geom="geometry") v$geometry <- NULL crs(v) <- crs(x) v } ) #setMethod("warp", signature(x="SpatRaster", y="SpatRaster"), # function(x, y, method="bilinear", filename="", overwrite=FALSE, ...) { # opt <- spatOptions(filename, overwrite, ...) # x@ptr <- x@ptr$warp(y@ptr, "", method, opt) # messages(x, "warp") # } #) terra/R/zzz.R0000644000175000017500000000153414201035747012710 0ustar nileshnilesh .gdinit <- function() { path = "" if (file.exists(system.file("proj/nad.lst", package = "terra")[1])) { path <- system.file("proj", package="terra") } .gdalinit(path) } loadModule("spat", TRUE) .onLoad <- function(libname, pkgname) { .gdinit() } .onAttach <- function(libname, pkgname) { packageStartupMessage("terra ", utils::packageVersion("terra")) .create_options() if (length(grep(.geos_version(FALSE, TRUE), .geos_version(TRUE))) != 1) { packageStartupMessage("WARNING: different compile-time and run-time versions of GEOS") packageStartupMessage("Compiled with:", .geos_version(FALSE, TRUE)) packageStartupMessage(" Running with:", .geos_version(TRUE, TRUE)) packageStartupMessage("\nYou should reinstall package 'terra'\n") } # terraOptions(todisk=TRUE, steps=2) # terraOptions(memfrac=0) } terra/R/gcp.R0000644000175000017500000000155014201035747012622 0ustar nileshnilesh setClass("GCP", representation ( gcp = "matrix" ), prototype ( gcp = cbind(fx=0, fy=0, tx=0, ty=0)[0,] ) ) setMethod("show", signature(object="GCP"), function(object) { m <- object@gcp show(m) if (!is.null(grDevices::dev.list())) { for (i in 1:nrow(m)) { graphics::arrows(m[i,1], m[i,2], x1 = m[i,3], y1 = m[i,4], col="red", length = 0.1) } } } ) #setMethod("add<-", signature(x="GCP"), # function(x, value) { # if (missing(value)) { # value <- terra:::RS_locator(2, "l") # value <- rbind(as.vector(t(value))) # } # if (ncol(value) == 4) { # x@gcp <- rbind(x@gcp, value) # } # if (!is.null(grDevices::dev.list())) { # graphics::arrows(value[1,1], value[1,2], x1 = value[1,3], y1 = value[1,4], col="red", length = 0.1) # } # x # } #) #gcp <- new("GCP") #gcp <- addGCP(gcp) terra/R/coerce.R0000644000175000017500000003051214201276744013315 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : October 2018 # Version 1.0 # License GPL v3 ## from stars #stars:::st_as_raster is used #setAs("stars", "SpatRaster") is provided by stars via st_as_raster from_stars <- function(from) { isProxy <- inherits(from, "stars_proxy") natts <- length(from) #from[i] recursion does not work with proxy if (!isProxy && (natts > 1)) { # not sure what attributes represent ra <- list() for (i in 1:natts) { ra[[i]] <- from_stars(from[i]) } if (all(sapply(ra, function(i) inherits(i, "SpatRaster")))) { nl <- sapply(ra, nlyr) ra <- rast(ra) nms <- names(ra) names(ra) <- paste(rep(names(from), nl), nms, sep="_") } else if (all(sapply(ra, function(i) inherits(i, "SpatRasterDataset")))) { ra <- do.call(c, ra) } else { ra <- lapply(ra, function(i) if (!inherits(i, "SpatRasterDataset")) {sds(i)} else {i}) ra <- do.call(c, ra) } return(ra) } dims <- attr(from, "dimensions") dd <- dim(from) # x, y hasBands <- "band" %in% names(dd) hasTime <- "time" %in% names(dd) timev <- NULL if (hasTime) { tim <- dims$time$offset tseq <- dims$time$from:dims$time$to if (dims$time$refsys == "Date") { timev <- as.Date(tim) + tseq } else { # for now timev <- tseq } } # no time or variables if (length(dd) - hasBands == 2) { return( methods::as(from, "SpatRaster")) } # time, perhaps bands or variables if (length(dd) - (hasTime + hasBands) == 2) { r <- methods::as(from, "SpatRaster") if (hasBands) { timev <- rep(timev, each=dd["band"]) } time(r) <- timev return(r) } if (isProxy) { # currently not setting time dim here if (natts > 1) { ff <- sapply(from, function(i) from[i][[1]]) s <- sds(ff) names(s) <- names(from) } else { f <- from[[1]] s <- sds(f) nms <- names(dd)[3+hasBands] if (!is.na(nms)) { names(s) <- paste(nms, 1:length(s), sep="-") } } return(s) } xmin <- dims$x$offset nc <- dims$x$to xmax <- xmin + nc * dims$x$delta ymax <- dims$y$offset nr <- dims$y$to ymin <- ymax + nr * dims$y$delta from <- from[[1]] rr <- list() if (hasTime && hasBands) { for (i in 1:dd[5]) { x <- from[,,,,i] r <- rast(ncols=nc, nrows=nr, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, crs=dims$x$refsys$wkt, nlyr=dd["band"] * dd["time"]) time(r) <- rep(timev, each=dd["band"]) bandnames <- rep(paste("band", 1:dd["band"], sep="-"), length(timev)) names(r) <- paste(bandnames, rep(timev, each=dd["band"]), sep="_") r <- setValues(r, as.vector(x)) rr[[i]] <- r } } else { #if (hasTime || hasBands) { for (i in 1:dd[4]) { x <- from[,,,i] r <- rast(ncols=nc, nrows=nr, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, crs=dims$x$refsys$wkt, nlyr=dim(x)[3], time=timev) if (hasBands) { names(r) <- paste("band", 1:dd["band"], sep="-") } else { names(r) <- timev } rr[[i]] <- setValues(r, x) } } s <- sds(rr) names(s) <- paste(names(dd)[4], 1:length(s), sep="-") s } setAs("stars", "SpatRasterDataset", function(from) { from_stars(from) } ) setAs("ggmap", "SpatRaster", function(from) { b <- attr(from, "bb") e <- ext(b$ll.lon, b$ur.lon, b$ll.lat, b$ur.lat) r <- rast(nrows=nrow(from), ncols=ncol(from), ext=e, nlyr=3, crs="epsg:4326", names=c("red", "green", "blue")) values(r) <- t(grDevices::col2rgb(from)) RGB(r) <- 1:3 r } ) as.list.SpatRaster <- function(x, ...) { lapply(1:nlyr(x), function(i) x[[i]]) } setMethod("as.list", signature(x="SpatRaster"), as.list.SpatRaster) # create a "grDevices::raster" (small r) object for use with the rasterImage function # NOT a raster::Raster* object setMethod("as.raster", signature(x="SpatRaster"), function(x, maxcell=500000, col) { if (missing(col)) { col <- rev(grDevices::terrain.colors(255)) } x <- spatSample(x, maxcell, method="regular", as.raster=TRUE) x <- as.matrix(x, wide=TRUE) r <- range(x, na.rm=TRUE) x <- (x - r[1])/ (r[2] - r[1]) x <- round(x * (length(col)-1) + 1) x[] <- col[x] as.raster(x) } ) .as.image <- function(x, maxcells=10000) { x <- spatSample(x, size=maxcells, method="regular", as.raster=TRUE) X <- xFromCol(x, 1:ncol(x)) Y <- yFromRow(x, nrow(x):1) Z <- t(as.matrix(x, wide=TRUE)[nrow(x):1,]) list(x=X, y=Y, z=Z) } setMethod("as.polygons", signature(x="SpatRaster"), function(x, trunc=TRUE, dissolve=TRUE, values=TRUE, na.rm=TRUE, extent=FALSE) { p <- methods::new("SpatVector") if (extent) { p@ptr <- x@ptr$dense_extent(FALSE, FALSE) x <- messages(x, "as.polygons") } else { opt <- spatOptions() p@ptr <- x@ptr$as_polygons(trunc[1], dissolve[1], values[1], na.rm[1], opt) x <- messages(x, "as.polygons") if (values) { ff <- is.factor(x) if (dissolve) { ff <- ff[[1]] } if (any(ff)) { ff <- which(ff) cgs <- cats(x) for (f in ff) { cg <- cgs[[f]] i <- match(unlist(p[[f]]), cg[,1]) act <- activeCat(x, f) p[[f]] <- cg[i, act+1] } } } } messages(p, "as.polygons") } ) setMethod("as.lines", signature(x="SpatRaster"), function(x) { p <- methods::new("SpatVector") opt <- spatOptions() p@ptr <- x@ptr$as_lines(opt) messages(p, "as.lines") } ) setMethod("as.polygons", signature(x="SpatExtent"), function(x, crs="") { p <- methods::new("SpatVector") crs <- character_crs(crs, "as.polygons") p@ptr <- SpatVector$new(x@ptr, crs) messages(p, "as.polygons") } ) setMethod("as.lines", signature(x="SpatExtent"), function(x, crs="") { crs <- character_crs(crs, "lines") as.lines(as.polygons(x, crs)) } ) setMethod("as.points", signature(x="SpatExtent"), function(x, crs="") { #vect(do.call(cbind, x@ptr$as.points()), "points", crs=crs) as.points(as.polygons(x, crs)) } ) setMethod("as.lines", signature(x="SpatVector"), function(x) { x@ptr <- x@ptr$as_lines() messages(x, "as.lines") } ) setMethod("as.polygons", signature(x="SpatVector"), function(x) { x@ptr <- x@ptr$polygonize() messages(x, "as.polygons") } ) setMethod("as.points", signature(x="SpatVector"), function(x, multi=FALSE, skiplast=TRUE) { opt <- spatOptions() x@ptr <- x@ptr$as_points(multi, skiplast) messages(x, "as.points") } ) setMethod("as.points", signature(x="SpatRaster"), function(x, values=TRUE, na.rm=TRUE) { p <- methods::new("SpatVector") opt <- spatOptions() p@ptr <- x@ptr$as_points(values, na.rm, opt) x <- messages(x, "as.points") if (values) { ff <- is.factor(x) if (any(ff)) { ff <- which(ff) levs <- levels(x) for (f in ff) { facts <- levs[[f]] v <- factor(unlist(p[[f]], use.names=FALSE), levels=(1:length(facts))-1) levels(v) <- facts p[[f]] <- as.character(v) } } } messages(p, "as.points") } ) # mode argument is ignored as mode=mode gave an error on R-devel setMethod("as.vector", signature(x="SpatExtent"), function(x, mode="any") { v <- x@ptr$vector names(v) <- c("xmin", "xmax", "ymin", "ymax") if (mode == "list") { v <- as.list(v) } v } ) setMethod("as.character", signature(x="SpatExtent"), function(x) { e <- as.vector(x) paste0("ext(", paste(e, collapse=", "), ")") } ) setMethod("as.vector", signature(x="SpatRaster"), function(x, mode="any") { values(x, FALSE) } ) as.matrix.SpatRaster <- function(x, ...) { if (!hasValues(x)) { error("as.matrix", "SpatRaster has no cell values") } wide <- isTRUE(list(...)$wide) if (wide) { if (nlyr(x) > 1) { m <- values(x, mat=TRUE) m <- lapply(1:ncol(m), function(i) { matrix(m[,i], nrow=nrow(x), byrow=TRUE) }) m <- do.call(cbind, m) } else { m <- matrix(values(x, mat=FALSE),nrow=nrow(x),byrow=TRUE) } } else { m <- values(x, mat=TRUE) } m } setMethod("as.matrix", signature(x="SpatRaster"), as.matrix.SpatRaster) as.data.frame.SpatRaster <- function(x, row.names=NULL, optional=FALSE, xy=FALSE, cells=FALSE, na.rm=TRUE, ...) { # dots <- list(...) # xy <- isTRUE(dots$xy) # cells <- isTRUE(dots$cells) # na.rm <- isTRUE(dots$na.rm) d <- NULL if (xy) { d <- xyFromCell(x, 1:ncell(x)) } if (cells) { d <- cbind(cell=1:ncell(x), d) } if (is.null(d)) { d <- values(x, dataframe=TRUE, ... ) } else { d <- data.frame(d) d <- cbind(d, values(x, dataframe=TRUE), ...) } if (na.rm) { d <- stats::na.omit(d) attr(d, "na.action") <- NULL } d } setMethod("as.data.frame", signature(x="SpatRaster"), as.data.frame.SpatRaster) setAs("SpatRaster", "data.frame", function(from) { as.data.frame(from) } ) setAs("SpatVector", "data.frame", function(from) { as.data.frame(from) } ) setMethod("as.array", signature(x="SpatRaster"), function(x) { dm <- dim(x) x <- values(x, TRUE) a <- array(NA, dm) for (i in 1:dm[3]) { a[,,i] <- matrix(x[,i], nrow=dm[1], byrow=TRUE) } a } ) # to sf from SpatVector # available in sf #.v2sf <- function(from) { # txt <- 'sf::st_as_sf(as.data.frame(from, geom=TRUE), wkt="geometry", crs=from@ptr$get_crs("wkt"))' # eval(parse(text = txt)) #} # sf bbox .ext_from_sf <- function(from) { sfi <- attr(from, "sf_column") geom <- from[[sfi]] e <- attr(geom, "bbox") ext(e[c(1,3,2,4)]) } .from_sf <- function(from) { sfi <- attr(from, "sf_column") geom <- from[[sfi]] crs <- attr(geom, "crs")$wkt if (is.na(crs)) crs <- "" #geom <- st_as_text(geom) #v <- vect(geom, crs=crs) v <- vect() v@ptr <- v@ptr$from_hex(sf::rawToHex(sf::st_as_binary(geom)), crs) if (ncol(from) > 1) { from[[sfi]] <- NULL values(v) <- as.data.frame(from) } v } setAs("sf", "SpatVector", function(from) { v <- try(.from_sf(from), silent=TRUE) if (inherits(v, "try-error")) { error("as,sf", "coercion failed. You can try coercing via a Spatial* (sp) class") } v } ) .from_sfc <- function(from) { v <- vect() v@ptr <- v@ptr$from_hex(sf::rawToHex(sf::st_as_binary(from)), "") crs(v) <- attr(from, "crs")$wkt v } setAs("sfc", "SpatVector", function(from) { v <- try(.from_sfc(from), silent=TRUE) if (inherits(v, "try-error")) { error("as,sfc", "coercion failed. You can try coercing via a Spatial* (sp) class") } v } ) setAs("sfg", "SpatVector", function(from) { v <- try(.from_sfc(from), silent=TRUE) if (inherits(v, "try-error")) { error("as,sfg", "coercion failed. You can try coercing via a Spatial* (sp) class") } v } ) setAs("XY", "SpatVector", function(from) { v <- try(.from_sfc(from), silent=TRUE) if (inherits(v, "try-error")) { error("as,sfc", "coercion failed. You can try coercing via a Spatial* (sp) class") } v } ) setAs("im", "SpatRaster", function(from) { r <- rast(nrows=from$dim[1], ncols=from$dim[2], xmin=from$xrange[1], xmax=from$xrange[2], ymin=from$yrange[1], ymax=from$yrange[2], crs="") values(r) <- from$v flip(r, direction="vertical") } ) setAs("SpatVector", "Spatial", function(from) { g <- geom(from, df=TRUE) geom(g, values(from), geomtype(from), crs(from)) } ) setAs("Spatial", "SpatVector", function(from) { g <- geom(from, df=TRUE) colnames(g)[1] <- "id" if (inherits(from, "SpatialPolygons")) { vtype <- "polygons" if ("cump" %in% colnames(g)) { g <- g[,c(1,2,5,6,4)] } } else if (inherits(from, "SpatialLines")) { vtype <- "lines" if ("cump" %in% colnames(g)) { g <- g[,colnames(g) != "cump"] } } else { vtype <- "points" g <- cbind(g[,1,drop=FALSE], part=1:nrow(g), g[,2:3,drop=FALSE]) } if (methods::.hasSlot(from, "data")) { v <- vect(g, vtype, from@data, crs(from)) } else { v <- vect(g, vtype, crs=crs(from)) } return(v) } ) setAs("SpatialGrid", "SpatRaster", function(from){ prj <- attr(from@proj4string, "comment") if (is.null(prj)) prj <- from@proj4string@projargs b <- rast(ext=as.vector(t(from@bbox)), crs=prj) if (inherits(from, "SpatialGridDataFrame")) { dim(b) <- c(from@grid@cells.dim[2], from@grid@cells.dim[1], ncol(from@data)) names(b) <- colnames(from@data) b <- setValues(b, as.matrix(from@data)) } else { dim(b) <- c(from@grid@cells.dim[2], from@grid@cells.dim[1]) } b } ) terra/R/image.R0000644000175000017500000000153614201035747013137 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : April 2019 # Version 1.0 # License GPL v3 .plot_image <- function(x, y=1, xlab="", ylab="", asp=NULL, ...) { X <- xFromCol(x, 1:ncol(x)) Y <- yFromRow(x, nrow(x):1) value <- matrix(as.vector(x), nrow=nrow(x), byrow=TRUE) value <- t(value[nrow(value):1, ,drop=FALSE]) if (is.null(asp)) { asp <- ifelse(is.lonlat(x, perhaps=TRUE, warn=FALSE), 1/cos((mean(as.vector(ext(x))[3:4]) * pi)/180), 1) graphics::image(x=X, y=Y, z=value, asp=asp, xlab=xlab, ylab=ylab, ...) } else { graphics::image(x=X, y=Y, z=value, xlab=xlab, ylab=ylab, ...) } } setMethod("image", signature(x="SpatRaster"), function(x, y=1, maxcell=50000, ...) { y <- as.integer(y[1]) stopifnot(y > 0 && y <= nlyr(x)) x <- spatSample(x[[y]], maxcell, method="regular", as.raster=TRUE) .plot_image(x, ...) } ) terra/R/RGB.R0000644000175000017500000001057114201035747012466 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : April 2010 # Version 0.9 # License GPL v3 setMethod("RGB<-", signature(x="SpatRaster"), function(x, value) { if (is.null(value[1]) || is.na(value[1])) { x@ptr$removeRGB() } else { stopifnot(all(value %in% 1:nlyr(x))) if (length(value) == 3) { x@ptr$setRGB(value[1]-1, value[2]-1, value[3]-1, -99, "rgb") } else if (length(value) == 4) { x@ptr$setRGB(value[1]-1, value[2]-1, value[3]-1, value[4]-1, "rgb") } else { error("RGB<-", "value must have length 3 or 4") } } messages(x, "RGB<-") } ) setMethod("RGB", signature(x="SpatRaster"), function(x) { if (x@ptr$rgb) { x@ptr$getRGB() + 1 } else { return(NULL) } } ) #### RGB2col make_cut <- function(x) { j <- length(x) out <- vector("list", 2*j) for (i in 1:j) { rgb <- x[[i]] if (NROW(rgb) <= 1) { out[[i]] <- rgb j <- j - 1 next } rng <- apply(rgb[,-1], 2, function(i) diff(range(i))) if (max(rng) == 0) { out[[i]] <- rgb j <- j - 1 next } p <- which.max(rng) + 1 m <- median(rgb[,p]) out[[i]] <- rgb[rgb[,p] >= m, ,drop=FALSE] out[[i+j]] <- rgb[rgb[,p] < m, ,drop=FALSE] } i <- sapply(out, is.null) out <- out[!i] i <- sapply(out, nrow) > 0 out[i] } median_cut <- function(v) { v <- list(v) n <- 0 while ((length(v) < 129) & (length(v) > n)) { n <- length(v) v <- make_cut(v) } s <- sapply(v, function(i) max(apply(i[,-1,drop=FALSE], 2, function(j) diff(range(j))))) n <- 256 - length(v) ss <- rev(sort(s)) ss <- max(2, min(ss[1:n])) i <- which(s > ss) if (length(i) > 0) { vv <- make_cut(v[i]) v <- c(v[-i], vv) } v <- lapply(1:length(v), function(i) cbind(group=i, v[[i]])) do.call(rbind, v) } rgb2col <- function(x, value, stretch=NULL, grays=FALSE, NAzero=FALSE, filename="", overwrite=FALSE, ...) { idx <- RGB(x) if (is.null(idx)) { if (missing(value)) { error("colorize", "x does not have an RGB attribute and the value argument is missing") } else { idx <- value } } n <- length(idx) stopifnot((n == 3) | (n == 4)) if ((min(idx) < 1) | (max(idx) > nlyr(x))) { error("colorize", "invalid value (RGB indices)") } x <- x[[idx]] if (!is.null(stretch)) { if (stretch == "lin") { x <- stretch(x, minq=0.02, maxq=0.98) } else { x <- stretch(x, histeq=TRUE, scale=255) } } if (n == 4) x[[4]] <- x[[4]] * 255 if (NAzero) { x <- classify(x, cbind(NA, 0)) } if (grays) { opt <- spatOptions(filename, overwrite, ...) x@ptr <- x@ptr$rgb2col(0, 1, 2, opt) return(messages(x, "colorize")) } v <- cbind(id=1:ncell(x), values(x)) v <- median_cut(stats::na.omit(v)) a <- aggregate(v[,-c(1:2)], list(v[,1]), median) if (n==3) { a$cols <- grDevices::rgb(a[,2], a[,3], a[,4], maxColorValue=255) } else { a$cols <- grDevices::rgb(a[,2], a[,3], a[,4], a[,5], maxColorValue=255) } m <- merge(v[,1:2], a[, c(1,n+2)], by=1) r <- rast(x, 1) r[m$id] <- m$group - 1 coltab(r) <- a$cols if (filename != "") { r <- writeRaster(r, filename, overwrite, ...) } r } col2rgb <- function(x, alpha=FALSE, filename="", overwrite=FALSE, ...) { if (nlyr(x) > 1) { x <- x[[1]] warn("colorize", "only the first layer of 'x' is considered") } ct <- coltab(r)[[1]] if (is.null(ct)) { error("error", "x has no color table") } ct <- as.matrix(ct) if (!alpha) { ct <- ct[,1:3] } r <- app(x, function(i) { ct[i+1, ,drop=FALSE] }, filename="", overwrite=FALSE, wopt=list(...)) RGB(r) <- 1:3 r } setMethod("colorize", signature(x="SpatRaster"), function(x, to="hsv", alpha=FALSE, stretch=NULL, grays=FALSE, NAzero=FALSE, filename="", overwrite=FALSE, ...) { to <- tolower(to) if (to %in% c("hsi", "hsl", "hsv")) { opt <- spatOptions(filename, overwrite, ...) x@ptr <- x@ptr$rgb2hsx(to, opt) } else if (to == "rgb") { if (nlyr(x) == 1) { return(col2rgb(x, alpha=alpha, filename=filename, overwrite=overwrite, ...)) } else { opt <- spatOptions(filename, overwrite, ...) x@ptr <- x@ptr$hsx2rgb(opt) } } else if (to == "hsl") { opt <- spatOptions(filename, overwrite, ...) x@ptr <- x@ptr$hsx2rgb(to, opt) } else if (to == "col") { return(rgb2col(x, stretch=stretch, grays=grays, NAzero=NAzero, filename=filename, overwrite=overwrite, ...)) } messages(x) } ) terra/R/extent.R0000644000175000017500000001227014201035747013361 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : October 2017 # Version 0.9 # License GPL v3 setMethod("ext", signature(x="SpatExtent"), function(x){ x@ptr <- x@ptr$deepcopy() x } ) setMethod("ext", signature(x="sf"), function(x){ sfi <- attr(x, "sf_column") geom <- x[[sfi]] e <- attr(geom, "bbox") ext(e[c(1,3,2,4)]) } ) setMethod("ext", signature(x="missing"), function(x){ e <- methods::new("SpatExtent") e@ptr <- SpatExtent$new() e } ) setMethod("ext", signature(x="numeric"), function(x, ...){ dots <- unlist(list(...)) x <- c(x, dots) if (length(x) < 4) { error("ext", "insufficient number of elements (should be 4)") } if (length(x) > 4) { warn("ext", "more elements than expected (should be 4)") } names(x) <- NULL e <- methods::new("SpatExtent") e@ptr <- SpatExtent$new(x[1], x[2], x[3], x[4]) if (methods::validObject(e)) return(e) } ) setMethod("ext", signature(x="SpatRaster"), function(x){ e <- methods::new("SpatExtent") e@ptr <- x@ptr$extent return(e) } ) setMethod("ext", signature(x="SpatRasterDataset"), function(x){ e <- methods::new("SpatExtent") e@ptr <- x[1]@ptr$extent return(e) } ) setMethod("ext<-", signature("SpatRaster", "SpatExtent"), function(x, value) { x@ptr$extent <- value@ptr messages(x, "ext<-") } ) setMethod("ext<-", signature("SpatRaster", "numeric"), function(x, value) { e <- ext(value) x@ptr <- x@ptr$deepcopy() x@ptr$extent <- e@ptr messages(x, "ext<-") } ) setMethod("set.ext", signature("SpatRaster"), function(x, value) { e <- ext(value) x@ptr$extent <- e@ptr messages(x, "set_ext") } ) setMethod("ext", signature(x="SpatVector"), function(x) { e <- methods::new("SpatExtent") e@ptr <- x@ptr$extent() e } ) setMethod("ext", signature(x="SpatVectorProxy"), function(x) { e <- methods::new("SpatExtent") e@ptr <- x@ptr$v$extent() e } ) setMethod("ext", signature(x="Extent"), function(x) { ext(as.vector(x)) } ) setMethod("ext", signature(x="Raster"), function(x) { ext(x@extent) } ) setMethod("ext", signature(x="Spatial"), function(x) { ext(as.vector(t(x@bbox))) } ) setMethod("xmin", signature(x="SpatExtent"), function(x){ x@ptr$vector[1] } ) setMethod("xmax", signature(x="SpatExtent"), function(x){ x@ptr$vector[2] } ) setMethod("ymin", signature(x="SpatExtent"), function(x){ x@ptr$vector[3] } ) setMethod("ymax", signature(x="SpatExtent"), function(x){ x@ptr$vector[4] } ) setMethod("xmin<-", signature("SpatExtent", "numeric"), function(x, value){ v <- as.vector(x) v[1] <- value ext(v) } ) setMethod("xmax<-", signature("SpatExtent", "numeric"), function(x, value){ v <- as.vector(x) v[2] <- value ext(v) } ) setMethod("ymin<-", signature("SpatExtent", "numeric"), function(x, value){ v <- as.vector(x) v[3] <- value ext(v) } ) setMethod("ymax<-", signature("SpatExtent", "numeric"), function(x, value){ v <- as.vector(x) v[4] <- value ext(v) } ) setMethod("xmin", signature(x="SpatRaster"), function(x){ xmin(ext(x)) } ) setMethod("xmax", signature(x="SpatRaster"), function(x){ xmax(ext(x)) } ) setMethod("ymin", signature(x="SpatRaster"), function(x){ ymin(ext(x)) } ) setMethod("ymax", signature(x="SpatRaster"), function(x){ ymax(ext(x)) } ) setMethod("xmin<-", signature("SpatRaster", "numeric"), function(x, value){ v <- as.vector(ext(x)) v[1] <- value x@ptr <- x@ptr$deepcopy() ext(x) <- ext(v) x } ) setMethod("xmax<-", signature("SpatRaster", "numeric"), function(x, value){ v <- as.vector(ext(x)) v[2] <- value x@ptr <- x@ptr$deepcopy() ext(x) <- ext(v) x } ) setMethod("ymin<-", signature("SpatRaster", "numeric"), function(x, value){ v <- as.vector(ext(x)) v[3] <- value x@ptr <- x@ptr$deepcopy() ext(x) <- ext(v) x } ) setMethod("ymax<-", signature("SpatRaster", "numeric"), function(x, value){ v <- as.vector(ext(x)) v[4] <- value x@ptr <- x@ptr$deepcopy() ext(x) <- ext(v) x } ) setMethod("xmin", signature(x="SpatVector"), function(x){ xmin(ext(x)) } ) setMethod("xmax", signature(x="SpatVector"), function(x){ xmax(ext(x)) } ) setMethod("ymin", signature(x="SpatVector"), function(x){ ymin(ext(x)) } ) setMethod("ymax", signature(x="SpatVector"), function(x){ ymax(ext(x)) } ) setMethod("$", "SpatExtent", function(x, name) { as.vector(x)[name] } ) setMethod("$<-", "SpatExtent", function(x, name, value) { e <- as.vector(x) e[name] <- value ext(e) } ) setMethod("[", c("SpatExtent", "missing", "missing"), function(x, i, j, ... , drop=FALSE) { as.vector(x) } ) setMethod("[", c("SpatExtent", "numeric", "missing"), function(x, i, j, ... , drop=FALSE) { x <- as.vector(x) x[i] } ) setReplaceMethod("[", c("SpatExtent", "numeric", "missing"), function(x, i, j, value) { e <- as.vector(x) stopifnot(all(i %in% 1:4)) e[i] <- value ext(e) } ) terra/R/tapp.R0000644000175000017500000000374414201035747013024 0ustar nileshnilesh setMethod("tapp", signature(x="SpatRaster"), function(x, index, fun, ..., cores=1, filename="", overwrite=FALSE, wopt=list()) { stopifnot(!any(is.na(index))) if (!is.factor(index)) { index <- as.factor(index) } nms <- as.character(index) ind <- as.integer(index) d <- unique(data.frame(nms, ind, stringsAsFactors=FALSE)) uin <- d[,2] nms <- make.names(d[,1]) nms <- nms[uin] txtfun <- .makeTextFun(fun) if (inherits(txtfun, "character")) { if (txtfun %in% .cpp_funs) { opt <- spatOptions(filename, overwrite, wopt=wopt) narm <- isTRUE(list(...)$na.rm) x@ptr <- x@ptr$apply(index, txtfun, narm, nms, opt) return(messages(x, "tapp")) } } fun <- match.fun(fun) nl <- nlyr(x) ind <- rep_len(index, nl) out <- rast(x) nlyr(out) <- length(uin) names(out) <- nms doclust <- FALSE if (inherits(cores, "cluster")) { doclust <- TRUE } else if (cores > 1) { doclust <- TRUE cores <- parallel::makeCluster(cores) on.exit(parallel::stopCluster(cores)) } readStart(x) on.exit(readStop(x), add=TRUE) b <- writeStart(out, filename, overwrite, wopt=wopt) if (doclust) { pfun <- function(x, ...) apply(x, 1, FUN=fun, ...) parallel::clusterExport(cores, "pfun", environment()) for (i in 1:b$n) { v <- readValues(x, b$row[i], b$nrows[i], 1, ncol(out), TRUE) v <- lapply(uin, function(i) v[, ind==i, drop=FALSE]) v <- parallel::parLapply(cores, v, pfun, ...) v <- do.call(cbind, v) writeValues(out, v, b$row[i], b$nrows[i]) } } else { for (i in 1:b$n) { v <- readValues(x, b$row[i], b$nrows[i], 1, ncol(out), TRUE) # like this, na.rm is not passed to FUN # v <- lapply(uin, function(j, ...) apply(v[, ind==uin[j], drop=FALSE], 1, FUN=fun, ...)) # like this it works v <- lapply(uin, function(j) apply(v[, ind==uin[j], drop=FALSE], 1, FUN=fun, ...)) v <- do.call(cbind, v) writeValues(out, v, b$row[i], b$nrows[i]) } } out <- writeStop(out) return(out) } ) terra/R/readsvg.R0000644000175000017500000000363014201035747013505 0ustar nileshnilesh transform <- function(xy, m) { newX = m[1] * xy[,1] + m[3] * xy[,2] + m[5] newY = m[2] * xy[,1] + m[4] * xy[,2] + m[6] cbind(newX, newY) } oneline <- function(x, id) { x <- trimws(gsub('^m', "", x)) ss <- trimws(unlist(strsplit(x, "m "))) out <- list() for (j in 1:length(ss)) { v <- unlist(utils::read.table(text=ss[j], sep=" ")) vv <- as.numeric(unlist(strsplit(v, ","))) vv <- matrix(vv, ncol=2, byrow=TRUE) if (j > 1) { vv[1,] <- vv[1,] + a[1,] } a <- apply(vv, 2, cumsum) out[[j]] <- a } out <- lapply(1:length(out), function(p) cbind(id=id, part=p, out[[p]], hole=0)) out <- do.call(rbind, out) out[,4] <- -out[,4] #out[,3:4] <- transform(out[,3:4], m) out } oneline2 <- function(x, id) { x <- trimws(gsub('^M', "", x)) ss <- trimws(unlist(strsplit(x, "ZM"))) out <- list() for (j in 1:length(ss)) { v <- unlist(strsplit(ss[j], "L")) v <- unlist(strsplit(v, "C")) v <- unlist(strsplit(v, " ")) v <- gsub("Z", "", v) vv <- as.numeric(unlist(strsplit(v, ","))) vv <- matrix(vv, ncol=2, byrow=TRUE) out[[j]] <- vv } out <- lapply(1:length(out), function(p) cbind(id=id, part=p, out[[p]], hole=0)) do.call(rbind, out) #out[,3:4] <- transform(out[,3:4], m) } readSVG <- function(f) { doc <- XML::htmlParse(f) p <- XML::xpathSApply(doc, "//path", XML::xmlGetAttr, "d") s <- list() for (i in 1:length(p)) { s[[i]] <- oneline2(p[i], i) } ss <- do.call(rbind, s) v <- vect(ss, type="polygons") a <- XML::xpathSApply(doc, "//path", XML::xmlAttrs) a <- unique(unlist(sapply(a, names))) a <- a[-grep(":", a)] a <- a[a != "d"] if (length(a) > 0) { att <- list() for (i in 1:length(a)) { z <- XML::xpathSApply(doc, "//path", XML::xmlGetAttr, a[i]) att[[i]] <- sapply(z, function(i) if (is.null(i)) NA else i, USE.NAMES = FALSE) } names(att) <- a values(v) <- data.frame(att) } v } terra/R/makeVRT.R0000644000175000017500000000770414201035747013371 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : October 2010, January 2022 # Version 1.0 # Licence GPL v3 gdalDType <- function(dtype) { dps <- c("INT2S", "INT4S", "INT1U", "INT2U", "INT4U", "FLT4S", "FLT8S") if (!(dtype %in% dps)) { stop(paste(dtype, "is not a valid data type. Should be one of:", paste(dps, collapse=", "))) } bytesize <- as.integer(substr(dtype, 4, 4)) size <- bytesize * 8 type <- substr(dtype, 1, 3) if (type == "INT") { type <- "Int" if (size == 64) { size <- 32 warning("8 byte integer values not supported by GDAL, changed to 4 byte integer values") } if (substr(dtype, 5, 5) == "U") { if (size == 8) { return(c("Byte", 1)) } else { type <- paste("U", type, sep="") } } } else { type <- "Float" } return(c(paste0(type, size), bytesize)) } makeVRT <- function(filename, nrow, ncol, nlyr=1, extent, xmin, ymin, xres, yres=xres, xycenter=TRUE, crs="+proj=longlat", lyrnms="", datatype, NAflag=NA, bandorder="BIL", byteorder="LSB", toptobottom=TRUE, offset=0, scale=1) { stopifnot(length(filename)==1) stopifnot(file.exists(filename)) if (tolower(tools::file_ext(filename)) == "vrt") { stop("cannot (over)write a vrt header for a vrt file") } lyrnms <- rep(lyrnms, length.out=nlyr) fvrt <- paste0(filename, ".vrt") if (missing(datatype)) { bytes <- file.info(filename)$size / (3601 * 3601) if (bytes == 1) { datatype <- "INT1U" } else if (bytes == 2) { datatype <- "INT2U" } else if (bytes == 4) { datatype <- "FLT4S" } else if (bytes == 8) { datatype <- "FLT8S" } } gd <- gdalDType(datatype[1]) datatype <- gd[1] pixsize <- as.integer(gd[2]) if (bandorder[1] == "BIL") { pixoff <- pixsize lineoff <- pixsize * ncol * nlyr imgoff <- ((1:nlyr)-1) * ncol * pixsize } else if (bandorder[1] == "BSQ") { pixoff <- pixsize lineoff <- pixsize * ncol imgoff <- ((1:nlyr)-1) * nrow*ncol * pixsize } else if (bandorder[1] == "BIP") { pixoff <- pixsize * nlyr lineoff <- pixsize * ncol * nlyr imgoff <- (1:nlyr)-1 } else { stop("unknown bandorder") } stopifnot(byteorder[1] %in% c("LSB", "MSB")) if (toptobottom[1]) { rotation <- 0 } else { rotation <- 180 } res <- abs(c(xres, yres)) if (missing(extent)) { if (xycenter) { xmin <- xmin - res[1]/2 ymin <- ymin - res[2]/2 } ymax <- ymin + nrow * res[2] } else { xmin <- xmin(extent) ymax <- ymax(extent) } f <- file(fvrt, "w") cat('\n' , sep = "", file = f) cat('', xmin, ', ', res[1], ', ', rotation, ', ', ymax, ', ', 0.0, ', ', -1*res[2], '\n', sep = "", file = f) if (! is.na(crs) ) { cat('', crs ,'\n', sep = "", file = f) } for (i in nlyr) { cat('\t\n', sep = "" , file = f) cat('\t\t', lyrnms[i], '\n', sep = "", file = f) cat('\t\t', basename(filename), '\n', sep = "", file = f) cat('\t\t', imgoff[i], '\n', sep = "", file = f) cat('\t\t', pixoff, '\n', sep = "", file = f) cat('\t\t', lineoff, '\n', sep = "", file = f) cat('\t\t', byteorder, '\n', sep = "", file = f) if (!is.na(NAflag)) { cat('\t\t', NAflag, '\n', sep = "", file = f) } if (isTRUE(offset != 0) || isTRUE(scale != 1)) { cat('\t\t', offset, '\n', sep = "", file = f) cat('\t\t', scale, '\n', sep = "", file = f) } cat('\t\n', sep = "", file = f) } cat('\n', sep = "", file = f) close(f) return(fvrt) } # a = makeVRT(ff[1], 3601, 3601, 1, xmin=37, ymin=37, xres=1/3600, lyrnms="aspect", datatype="INT2U", byteorder="MSB") terra/R/focal.R0000644000175000017500000003177214202115424013136 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : December 2017 # Version 1.0 # License GPL v3 setMethod("focal", signature(x="SpatRaster"), function(x, w=3, fun="sum", ..., na.policy="all", fillvalue=NA, expand=FALSE, silent=TRUE, filename="", overwrite=FALSE, wopt=list()) { na.only <- list(...)$na.only if (!is.null(na.only)) { warn("focal", "use 'na.policy' instead of 'na.only'") na.policy <- "only" } na.policy <- match.arg(tolower(na.policy), c("all", "only", "omit")) na.only <- na.policy == "only" na.omit <- na.policy == "omit" if (!is.numeric(w)) { error("focal", "w should be numeric vector or matrix") } txtfun <- .makeTextFun(fun) if (is.matrix(w)) { m <- as.vector(t(w)) if (!all(m %in% c(0, 1, NA))) { if (isTRUE(list(...)$na.rm)) { if (txtfun != "sum") { error("focal", 'with "na.rm=TRUE" and weights other than 0, 1, or NA, only fun="sum" is allowed') } } } w <- dim(w) } else { w <- rep_len(w, 2) stopifnot(all(w > 0)) m <- rep(1, prod(w)) } cpp <- FALSE txtfun <- .makeTextFun(fun) if (is.character(txtfun)) { if (is.null(wopt$names)) { wopt$names <- paste0("focal_", txtfun) } opt <- spatOptions(filename, overwrite, wopt=wopt) narm <- isTRUE(list(...)$na.rm) if (na.only && (!narm)) { error("focal", "combining 'na.only=TRUE' with 'na.rm=FALSE' has no effect") } x@ptr <- x@ptr$focal(w, m, fillvalue, narm, na.only, na.omit, txtfun, expand, opt) messages(x, "focal") return(x) } else { if (expand) { warn(focal, "expand is ignored for non-standard functions") } checkNA <- na.only || na.omit msz <- prod(w) dow <- !isTRUE(all(m == 1)) if (any(is.na(m))) { k <- !is.na(m) mm <- m[k] msz <- sum(k) } v <- focalValues(x, w, trunc(nrow(x)/2), 1)[ncol(x)/2, ,drop=FALSE] if (dow) { if (any(is.na(m))) { v <- v[k] * mm } else { v <- v * m } } test <- try(apply(v, 1, fun, ...), silent=silent) if (inherits(test, "try-error")) { error("focal", "test failed") } readStart(x) on.exit(readStop(x)) nl <- nlyr(x) outnl <- nl * length(test) transp <- FALSE nms <- NULL if (isTRUE(nrow(test) > 1)) { transp <- TRUE nms <- rownames(test) } else if (isTRUE(ncol(test) > 1)) { nms <- colnames(test) } out <- rast(x, nlyr=outnl) if (!is.null(nms)) { names(out) <- nms } b <- writeStart(out, filename, overwrite, n=msz*4, wopt=wopt) opt <- spatOptions() for (i in 1:b$n) { vv <- NULL for (j in 1:nl) { if (nl > 1) { v <- x[[j]]@ptr$focalValues(w, fillvalue, b$row[i]-1, b$nrows[i], opt) } else { v <- x@ptr$focalValues(w, fillvalue, b$row[i]-1, b$nrows[i], opt) } if (dow) { if (any(is.na(m))) { v <- v[k] * mm } else { v <- v * m } } v <- matrix(v, ncol=msz, byrow=TRUE) v <- apply(v, 1, fun, ...) if (transp) { v <- t(v) } if (checkNA) { vv <- readValues(x, b$row[i], b$nrows[i]) if (na.only) { j <- !is.na(vv) } else { j <- is.na(vv) } v[j] <- vv[j] } if (nl > 1) { if (outnl > 1) { vv <- rbind(vv, v) } else { vv <- c(vv, v) } } } #if (bip) { # v <- matrix(as.vector(v), ncol=ncol(v), byrow=TRUE) #} if (nl > 1) { writeValues(out, vv, b$row[i], b$nrows[i]) } else { writeValues(out, v, b$row[i], b$nrows[i]) } } out <- writeStop(out) return(out) } } ) setMethod("focal3D", signature(x="SpatRaster"), function(x, w=3, fun=mean, ..., na.policy="all", fillvalue=NA, pad=FALSE, padvalue=fillvalue, expand=FALSE, silent=TRUE, filename="", overwrite=FALSE, wopt=list()) { na.policy <- match.arg(tolower(na.policy), c("all", "only", "omit")) na.only <- na.policy == "only" na.omit <- na.policy == "omit" checkNA <- na.only || na.omit if (!(inherits(w, "numeric") || inherits(w, "array"))) { error("focal3D", "w should be numeric vector or array") } if (is.array(w)) { if (length(dim(w)) != 3) { error("focal3D", "the weights array must have three dimensions") } m <- as.vector(w) w <- dim(w) } else { w <- rep_len(w, 3) stopifnot(all(w > 0)) m <- rep(1, prod(w)) } if (w[3] > nlyr(x)) { error("focal", "the third weights dimension is larger than nlyr(x)") } msz <- prod(w) dow <- !isTRUE(all(m == 1)) rna <- FALSE if (any(is.na(m))) { rna <- TRUE kna <- !is.na(m) m <- m[kna] msz <- sum(kna) } opt <- spatOptions() halfway <- floor(w[3]/2) v <- lapply(1:w[3], function(i) focalValues(x[[i]], w[1:2], trunc(nrow(x)/2), 1)[ncol(x)/2, ,drop=FALSE]) v <- t(do.call(cbind, v)) if (dow) { if (rna) { v <- v[kna,,drop=FALSE] * m } else { v <- v * m } } vout <- try(apply(v, 2, fun, ...), silent=silent) if (inherits(vout, "try-error")) { error("focal", "test failed") } readStart(x) on.exit(readStop(x)) nl <- nlyr(x) transp <- FALSE nms <- NULL if (isTRUE(nrow(vout) > 1)) { transp <- TRUE nms <- rownames(vout) } else if (isTRUE(ncol(vout) > 1)) { nms <- colnames(vout) } if (pad || expand) { startlyr = 1; endlyr = nl; outnl <- nl * length(vout) } else { startlyr = halfway+1; endlyr = nl-halfway; outnl <- (1+endlyr-startlyr) * length(vout) } out <- rast(x, nlyr=outnl) if (!is.null(nms)) { names(out) <- nms } b <- writeStart(out, filename, overwrite, n=msz*4, wopt=wopt) nread <- prod(w[1:2]) for (i in 1:b$n) { nc <- b$nrows[i]*ncol(x) vv <- NULL if (expand) { v <- list(matrix(x[[1]]@ptr$focalValues(w, fillvalue, b$row[i]-1, b$nrows[i], opt), ncol=nc)) v <- do.call(rbind, rep(v, halfway+1)) for (k in 2:(1+halfway)) { v <- rbind(v, matrix(x[[k]]@ptr$focalValues(w, fillvalue, b$row[i]-1, b$nrows[i], opt), ncol=nc)) } } else if (pad) { v <- matrix(padvalue, ncol=b$nrows[i]*ncol(x), nrow=nread*halfway) for (k in 1:(1+halfway)) { v <- rbind(v, matrix(x[[k]]@ptr$focalValues(w, fillvalue, b$row[i]-1, b$nrows[i], opt), ncol=nc)) } } else { v <- lapply(1:w[3], function(k) matrix(x[[k]]@ptr$focalValues(w, fillvalue, b$row[i]-1, b$nrows[i], opt), ncol=nc)) v <- do.call(rbind, v) } for (j in startlyr:endlyr) { if (j > startlyr) { v <- v[-c(1:nread), ] k <- j + halfway if (k > nl) { if (pad) { v <- rbind(v, matrix(padvalue, nrow=nread, ncol=ncol(v))) } else { v <- rbind(v, v[(nrow(v)-nread):nrow(v), ]) } } else { v <- rbind(v, matrix(x[[k]]@ptr$focalValues(w, fillvalue, b$row[i]-1, b$nrows[i], opt), ncol=ncol(v))) } } if (dow) { if (rna) { vout <- apply(v[kna,] * m, 2, fun, ...) } else { vout <- apply(v * m, 2, fun, ...) } } else { vout <- apply(v, 2, fun,...) } if (transp) { vout <- t(vout) } if (checkNA) { vv <- readValues(x, b$row[i], b$nrows[i]) if (na.only) { j <- !is.na(vv) } else { j <- is.na(vv) } vout[j] <- vv[j] } vv <- c(vv, as.vector(vout)) } writeValues(out, vv, b$row[i], b$nrows[i]) } out <- writeStop(out) return(out) } ) setMethod("focalCpp", signature(x="SpatRaster"), function(x, w=3, fun, ..., fillvalue=NA, silent=TRUE, filename="", overwrite=FALSE, wopt=list()) { if (!(all(c("ni", "nw") %in% names(formals(fun))))) { error("focalRaw", 'fun must have an argument "ni"') } if (!is.numeric(w)) { error("focal", "w should be numeric vector or matrix") } if (is.matrix(w)) { m <- as.vector(t(w)) w <- dim(w) } else { w <- rep_len(w, 2) stopifnot(all(w > 0)) m <- rep(1, prod(w)) } msz <- prod(w) readStart(x) on.exit(readStop(x)) dow <- !isTRUE(all(m == 1)) if (any(is.na(m))) { k <- !is.na(m) mm <- m[k] msz <- sum(k) } opt <- spatOptions() nl <- nlyr(x) v <- x@ptr$focalValues(w, fillvalue, max(0, trunc(nrow(x)/2)), 1, opt)[1:prod(w)] if (dow) { if (any(is.na(m))) { v <- v[k] * mm } else { v <- v * m } } test <- try(fun(v, ..., ni=1, nw=msz), silent=silent) if (inherits(test, "try-error")) { error("focalCpp", "test failed") } outnl <- nl * length(test) if (is.null(wopt$names )) { wopt$names <- colnames(test) } out <- rast(x, nlyr=outnl) b <- writeStart(out, filename, overwrite, n=msz*4, wopt=wopt) nc <- ncol(out) for (i in 1:b$n) { vv <- NULL for (j in 1:nl) { if (nl > 1) { v <- x[[j]]@ptr$focalValues(w, fillvalue, b$row[i]-1, b$nrows[i], opt) } else { v <- x@ptr$focalValues(w, fillvalue, b$row[i]-1, b$nrows[i], opt) } sst <- messages(x) if (dow) { if (any(is.na(m))) { v <- v[k] * mm } else { v <- v * m } } v <- fun(v, ..., ni=b$nrows[i]*nc, nw=msz) if (nl > 1) { if (outnl > 1) { vv <- rbind(vv, v) } else { vv <- c(vv, v) } } } if (nl > 1) { writeValues(out, vv, b$row[i], b$nrows[i]) } else { writeValues(out, v, b$row[i], b$nrows[i]) } } writeStop(out) } ) setMethod("focalReg", signature(x="SpatRaster"), function(x, w=3, na.rm=TRUE, fillvalue=NA, filename="", ...) { ols <- function(x, y) { v <- cbind(y, x) X <- cbind(1, v[,-1]) XtX <- t(X) %*% X if (det(XtX) == 0) { return(NA) } invXtX <- solve(XtX) %*% t(X) invXtX %*% v[,1] } ols_narm <- function(x, y) { v <- na.omit(cbind(y, x)) if (nrow(v) < (NCOL(x) + 1)) { return(NA) } X <- cbind(1, v[,-1]) XtX <- t(X) %*% X if (det(XtX) == 0) { return(NA) } invXtX <- solve(XtX) %*% t(X) invXtX %*% v[,1] } nl <- nlyr(x) if (nl < 2) error("focalReg", "x must have at least 2 layers") if (!is.numeric(w)) { error("focalReg", "w should be numeric vector or matrix") } if (is.matrix(w)) { m <- as.vector(t(w)) w <- dim(w) } else { w <- rep_len(w, 2) stopifnot(all(w > 0)) m <- rep(1, prod(w)) } msz <- prod(w) dow <- !isTRUE(all(m == 1)) isnam <- FALSE if (any(is.na(m))) { k <- !is.na(m) mm <- m[k] msz <- sum(k) isnam <- TRUE } out <- rast(x) if (na.rm) { fun = function(x, y) { x <- try(ols_narm(x, y), silent=TRUE) } #fun = ols_narm } else { fun = function(x, y) try(ols(x, y), silent=TRUE) #fun = ols } names(out) <- paste0("B", 0:(nl-1)) b <- writeStart(out, filename, n=msz*4, ...) ry <- x[[1]] rx <- x[[-1]] if (nl == 2) { for (i in 1:b$n) { Y <- focalValues(ry, w, b$row[i], b$nrows[i], fillvalue) X <- focalValues(rx, w, b$row[i], b$nrows[i], fillvalue) if (dow) { if (isnam) { Y <- Y[k] * mm X <- X[k] * mm } else { Y <- Y * m X <- X * m } } v <- t(sapply(1:nrow(Y), function(i) fun(X[i,], Y[i,]))) writeValues(out, v, b$row[i], b$nrows[i]) } } else { for (i in 1:b$n) { Y <- focalValues(ry, w, b$row[i], b$nrows[i], fillvalue) if (dow) { if (isnam) { Y <- Y[k] * mm } else { Y <- Y * m } } X <- list() for (j in 1:(nl-1)) { X[[j]] <- focalValues(rx[[j]], w, b$row[i], b$nrows[i], fillvalue) if (dow) { if (any(is.na(m))) { X[[j]] <- X[[j]][k] * mm } else { X[[j]] <- X[[j]] * m } } } v <- list() for (p in 1:nrow(Y)) { xlst <- list() for (j in 1:(nl-1)) { xlst[[j]] <- X[[j]][p,] } pX <- do.call(cbind, xlst) v[[p]] <- fun(pX, Y[p,]) } v <- t(do.call(cbind, v)) writeValues(out, v, b$row[i], b$nrows[i]) } } out <- writeStop(out) return(out) } ) setMethod("focalCor", signature(x="SpatRaster"), function(x, w=3, fun, ..., fillvalue=NA, filename="", overwrite=FALSE, wopt=list()) { nl <- nlyr(x) if (nl < 2) error("focalCor", "x must have at least 2 layers") if (!is.numeric(w)) { error("focalCor", "w should be numeric vector or matrix") } if (is.matrix(w)) { m <- as.vector(t(w)) w <- dim(w) } else { w <- rep_len(w, 2) stopifnot(all(w > 0)) m <- rep(1, prod(w)) } msz <- prod(w) dow <- !isTRUE(all(m == 1)) isnam <- FALSE if (any(is.na(m))) { k <- !is.na(m) mm <- m[k] msz <- sum(k) isnam <- TRUE } test <- do.call(fun, list(1:prod(w), prod(w):1), ...) if (is.null(wopt$names )) { wopt$names <- colnames(test) } outnl <- (nlyr(x) - 1) * length(test) out <- rast(x, nlyr=outnl) b <- writeStart(out, filename, n=msz*4, ...) v <- list() for (i in 1:b$n) { Y <- focalValues(x[[1]], w, b$row[i], b$nrows[i], fillvalue) if (dow) { if (isnam) { Y <- Y[k] * mm } else { Y <- Y * m } } for (j in 2:nlyr(x)) { X <- Y Y <- focalValues(x[[j]], w, b$row[i], b$nrows[i], fillvalue) if (dow) { if (isnam) { Y <- Y[k] * mm } else { Y <- Y * m } } v[[j-1]] <- t(sapply(1:nrow(Y), function(i, ...) fun(X[i,], Y[i,], ...))) } v <- do.call(cbind, v) writeValues(out, v, b$row[i], b$nrows[i]) } out <- writeStop(out) return(out) } ) terra/R/plotRGB.R0000644000175000017500000001055514202622506013363 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : April 2010 # Version 0.9 # License GPL v3 .linStretch <- function (x) { v <- stats::quantile(x, c(0.02, 0.98), na.rm = TRUE) temp <- (255 * (x - v[1]))/(v[2] - v[1]) temp[temp < 0] <- 0 temp[temp > 255] <- 255 return(temp) } # Histogram equalization stretch .eqStretch <- function(x){ ecdfun <- stats::ecdf(x) ecdfun(x)*255 } rgbstretch <- function(RGB, stretch, caller="") { stretch = tolower(stretch) if (stretch == 'lin') { RGB[,1] <- .linStretch(RGB[,1]) RGB[,2] <- .linStretch(RGB[,2]) RGB[,3] <- .linStretch(RGB[,3]) } else if (stretch == 'hist') { RGB[,1] <- .eqStretch(RGB[,1]) RGB[,2] <- .eqStretch(RGB[,2]) RGB[,3] <- .eqStretch(RGB[,3]) } else if (stretch != '') { warn(caller, "invalid stretch value") } RGB } setMethod("plotRGB", signature(x="SpatRaster"), function(x, r=1, g=2, b=3, a=NULL, scale, maxcell=500000, mar=0, stretch=NULL, ext=NULL, smooth=FALSE, colNA="white", alpha, bgalpha, addfun=NULL, zlim=NULL, zlimcol=NULL, axes=FALSE, xlab="", ylab="", asp=NULL, add=FALSE, interpolate, ...) { x <- x[[c(r, g, b, a)]] if (!is.null(mar)) { mar <- rep_len(mar, 4) if (!any(is.na(mar))) { graphics::par(mar=mar) } } if (missing(scale)) { scale <- 255 if ( all(hasMinMax(x)) ) { rng <- minmax(x)[, 1:3] scale <- max(max(rng[2]), 255) } } scale <- as.vector(scale)[1] if (!is.null(ext)) { x <- crop(x, ext) } x <- spatSample(x, maxcell, method="regular", as.raster=TRUE) if (!is.null(zlim)) { if (length(zlim) == 2) { zlim <- sort(zlim) if (is.null(zlimcol)) { x <- clamp(x, zlim[1], zlim[2], values=TRUE) } else { #if (is.na(zlimcol)) { x <- clamp(x, zlim[1], zlim[2], values=FALSE) } } else if (NROW(zlim) == 3 & NCOL(zlim) == 2) { for (i in 1:3) { zmin <- min(zlim[i,]) zmax <- max(zlim[i,]) if (is.null(zlimcol)) { x[[i]] <- clamp(x[[i]], zmin, zmax, values=TRUE) } else { #if (is.na(zlimcol)) { x[[i]] <- clamp(x[[i]], zmin, zmax, values=FALSE) } } } else { error('zlim should be a vector of two numbers or a 3x2 matrix (one row for each color)') } } if (!is.null(stretch)) { if (stretch == "lin") { x <- stretch(x, minq=0.02, maxq=0.98) } else { x <- stretch(x, histeq=TRUE, scale=255) } scale <- 255 } RGB <- values(x) RGB <- stats::na.omit(RGB) naind <- as.vector( attr(RGB, "na.action") ) if (!is.null(a)) { alpha <- RGB[,4] * 255 RGB <- RGB[,-4] } if (!is.null(naind)) { bg <- grDevices::col2rgb(colNA) bg <- grDevices::rgb(bg[1], bg[2], bg[3], alpha=bgalpha, maxColorValue=255) z <- rep( bg, times=ncell(x)) z[-naind] <- grDevices::rgb(RGB[,1], RGB[,2], RGB[,3], alpha=alpha, maxColorValue=scale) } else { z <- grDevices::rgb(RGB[,1], RGB[,2], RGB[,3], alpha=alpha, maxColorValue=scale) } z <- matrix(z, nrow=nrow(x), ncol=ncol(x), byrow=TRUE) requireNamespace("grDevices") bb <- as.vector(matrix(as.vector(ext(x)), ncol=2)) bb <- as.vector(ext(x)) if (!add) { #if ((!axes) & (!margins)) { # old.par <- graphics::par(no.readonly =TRUE) # on.exit(graphics::par(old.par)) # graphics::par(plt=c(0,1,0,1)) #} if (is.null(asp)) { if (is.lonlat(x, perhaps=TRUE, warn=FALSE)) { ym <- mean(bb[3:4]) asp <- 1/cos((ym * pi)/180) #asp <- min(5, 1/cos((ym * pi)/180)) } else { asp <- 1 } } xlim=c(bb[1], bb[2]) ylim=c(bb[3], bb[4]) plot(NA, NA, xlim=xlim, ylim=ylim, type = "n", xaxs='i', yaxs='i', xlab=xlab, ylab=ylab, asp=asp, axes=FALSE, ...) if (axes) { xticks <- graphics::axTicks(1, c(xlim[1], xlim[2], 4)) yticks <- graphics::axTicks(2, c(ylim[1], ylim[2], 4)) if (xres(x) %% 1 == 0) xticks = round(xticks) if (yres(x) %% 1 == 0) yticks = round(yticks) graphics::axis(1, at=xticks) graphics::axis(2, at=yticks, las = 1) #graphics::axis(3, at=xticks, labels=FALSE, lwd.ticks=0) #graphics::axis(4, at=yticks, labels=FALSE, lwd.ticks=0) graphics::box() } } if (!missing(interpolate)) { # for backwards compatibility if (is.logical(interpolate)) { smooth <- interpolate } } graphics::rasterImage(z, bb[1], bb[3], bb[2], bb[4], interpolate=smooth, ...) if (!is.null(addfun)) { if (is.function(addfun)) { addfun() } } } ) terra/R/values.R0000644000175000017500000002015214201035747013347 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : June 2008 # Version 0.9 # License GPL v3 setMethod("hasValues", signature(x="SpatRaster"), function(x) { x@ptr$hasValues } ) .makeDataFrame <- function(x, v, factors=TRUE, ...) { v <- data.frame(v, check.names=FALSE, ...) if (factors) { ff <- is.factor(x) if (any(ff)) { ff <- which(ff) cgs <- cats(x) for (f in ff) { cg <- cgs[[f]] i <- match(v[,f], cg[,1]) act <- activeCat(x, f) + 1 if (!inherits(cg[[act]], "numeric")) { v[[f]] <- factor(cg[i, act], levels=unique(cg[[act]])) } else { v[[f]] <- cg[i, act] } } } else { bb <- is.bool(x) if (any(bb)) { for (b in which(bb)) { v[[b]] = as.logical(v[[b]]) } } ii <- is.int(x) if (any(ii)) { for (i in which(ii)) { v[[i]] = as.integer(v[[i]]) } } } } else { bb <- is.bool(x) if (any(bb)) { for (b in which(bb)) { v[[b]] = as.logical(v[[b]]) } } ii <- is.int(x) if (any(ii)) { for (i in which(ii)) { v[[i]] = as.integer(v[[i]]) } } } v } setMethod("readValues", signature(x="SpatRaster"), function(x, row=1, nrows=nrow(x), col=1, ncols=ncol(x), mat=FALSE, dataframe=FALSE, ...) { stopifnot(row > 0 && nrows > 0) stopifnot(col > 0 && ncols > 0) v <- x@ptr$readValues(row-1, nrows, col-1, ncols) messages(x, "readValues") if (dataframe || mat) { v <- matrix(v, ncol = nlyr(x)) colnames(v) <- names(x) if (dataframe) { return(.makeDataFrame(x, v, factors=TRUE, ...) ) } } v } ) setMethod("values", signature(x="SpatRaster"), function(x, mat=TRUE, dataframe=FALSE, row=1, nrows=nrow(x), col=1, ncols=ncol(x), na.rm=FALSE, ...) { readStart(x) on.exit(readStop(x)) v <- readValues(x, row, nrows, col, ncols, mat=mat, dataframe=dataframe, ...) messages(x, "values") if (na.rm) { if (!is.null(dim(v))) { v[stats::complete.cases(v), , drop=FALSE] } else { v[!is.na(v)] } } else { v } } ) setMethod("values<-", signature("SpatRaster", "ANY"), function(x, value) { setValues(x, value) } ) setMethod("focalValues", signature("SpatRaster"), function(x, w=3, row=1, nrows=nrow(x), fill=NA) { if (is.matrix(w)) { #m <- as.vector(t(w)) w <- dim(w) } else { w <- rep_len(w, 2) } readStart(x) on.exit(readStop(x)) opt <- spatOptions() m <- matrix(x@ptr$focalValues(w, fill, max(0, row-1), nrows, opt), ncol=prod(w), byrow=TRUE) messages(x, "focalValues") m } ) setMethod("setValues", signature("SpatRaster"), function(x, values, keeptime=TRUE, keepunits=TRUE, props=FALSE) { y <- rast(x, keeptime=keeptime, keepunits=keepunits, props=props) if (is.matrix(values)) { if (nrow(values) == nrow(x)) { values <- as.vector(t(values)) } else { values <- as.vector(values) } } else if (is.array(values)) { stopifnot(length(dim(values)) == 3) values <- as.vector(aperm(values, c(2,1,3))) } make_factor <- FALSE set_coltab <- FALSE if (is.character(values)) { if (all(substr(na.omit(values), 1, 1) == "#")) { fv <- as.factor(values) if (length(levels(fv)) <= 256) { values <- as.integer(fv)-1 fv <- levels(fv) set_coltab <- TRUE } else { fv <- NULL values <- t(grDevices::col2rgb(values)) y <- rast(y, nlyr=3, names=c("red", "green", "blue")) RGB(y) <- 1:3 } } else { values <- as.factor(values) levs <- levels(values) values <- as.integer(values) - 1 # -1 not needed anymore? make_factor <- TRUE } } else if (is.factor(values)) { levs <- levels(values) values <- as.integer(values) - 1 make_factor <- TRUE } if (!(is.numeric(values) || is.integer(values) || is.logical(values))) { error("setValues", "values must be numeric, integer, logical, factor or character") } lv <- length(values) nc <- ncell(y) nl <- nlyr(y) opt <- spatOptions() if (lv == 1) { y@ptr$setValues(values, opt) } else { if (lv > (nc * nl)) { warn("setValues", "values is larger than the size of cells") values <- values[1:(nc*nl)] } else if (lv < (nc * nl)) { warn("setValues", "values were recycled") values <- rep(values, length.out=nc*nl) } y@ptr$setValues(values, opt) } y <- messages(y, "setValues") if (make_factor) { for (i in 1:nlyr(y)) { set.cats(y, i, levs, 2) } } if (set_coltab) { coltab(y) <- fv } else if (is.logical(values)) { y@ptr$setValueType(3) } else if (is.integer(values)) { y@ptr$setValueType(1) } y } ) setMethod("inMemory", signature(x="SpatRaster"), function(x, bylayer=FALSE) { r <- x@ptr$inMemory if (bylayer) { nl <- .nlyrBySource(x) r <- rep(r, nl) } r } ) #..hasValues <- function(x) { x@ptr$hasValues} #..inMemory <- function(x) { x@ptr$inMemory } #..filenames <- function(x) { x@ptr$filenames } setMethod("sources", signature(x="SpatRaster"), function(x, nlyr=FALSE, bands=FALSE) { src <- x@ptr$filenames Encoding(src) <- "UTF-8" if (bands) { nls <- x@ptr$nlyrBySource() d <- data.frame(sid=rep(1:length(src), nls), source=rep(src, nls), bands=x@ptr$getBands()+1, stringsAsFactors=FALSE) if (nlyr) { d$nlyr <- rep(nls, nls) } d } else if (nlyr) { data.frame(source=src, nlyr=x@ptr$nlyrBySource(), stringsAsFactors=FALSE) } else { src } } ) setMethod("hasMinMax", signature(x="SpatRaster"), function(x) { x@ptr$hasRange } ) setMethod("minmax", signature(x="SpatRaster"), function(x) { have <- x@ptr$hasRange if (!any(have)) { warn("minmax", "min and max values not available. See 'setMinMax' or 'global'") } r <- rbind(x@ptr$range_min, x@ptr$range_max) r[,!have] <- c(Inf, -Inf) colnames(r) <- names(x) r } ) setMethod("setMinMax", signature(x="SpatRaster"), function(x, force=FALSE) { opt <- spatOptions() if (force) { x@ptr$setRange(opt) } else if (!all(hasMinMax(x))) { x@ptr$setRange(opt) } x <- messages(x, "setMinMax") } ) setMethod("compareGeom", signature(x="SpatRaster", y="SpatRaster"), function(x, y, ..., lyrs=FALSE, crs=TRUE, warncrs=FALSE, ext=TRUE, rowcol=TRUE, res=FALSE, stopOnError=TRUE) { dots <- list(...) opt <- spatOptions("") res <- x@ptr$compare_geom(y@ptr, lyrs, crs, opt$tolerance, warncrs, ext, rowcol, res) if (stopOnError) messages(x, "compareGeom") if (length(dots)>1) { for (i in 1:length(dots)) { bool <- x@ptr$compare_geom(dots[[i]]@ptr, lyrs, crs, warncrs, ext, rowcol, res) if (stopOnError) messages(x, "compareGeom") res <- bool & res } } res } ) setMethod("values", signature("SpatVector"), function(x, ...) { as.data.frame(x, ...) } ) setMethod("values<-", signature("SpatVector", "data.frame"), function(x, value) { stopifnot(nrow(x) == nrow(value)) x <- x[,0] # use cbind instead types <- sapply(value, class) nms <- colnames(value) for (i in 1:ncol(value)) { if (types[i] == "numeric") { x@ptr$add_column_double(value[[i]], nms[i]) } else if (types[i] == "integer") { x@ptr$add_column_long(value[[i]], nms[i]) } else if (types[i] == "character") { x@ptr$add_column_string(value[[i]], nms[i]) } else { att <- as.character(value[[i]]) x@ptr$add_column_string(att, nms[i]) } } x } ) setMethod("values<-", signature("SpatVector", "matrix"), function(x, value) { `values<-`(x, data.frame(value)) } ) setMethod("values<-", signature("SpatVector", "ANY"), function(x, value) { if (!is.vector(value)) { error("values<-", "the values must be a data.frame, matrix or vector") } value <- rep(value, length.out=nrow(x)) value <- data.frame(value=value) `values<-`(x, data.frame(value)) } ) setMethod("values<-", signature("SpatVector", "NULL"), function(x, value) { x@ptr$remove_df() x } ) setMethod("setValues", signature("SpatVector"), function(x, values) { x@ptr <- x@ptr$deepcopy() `values<-`(x, values) } ) terra/R/math.R0000644000175000017500000000577414201035747013016 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : September 2018 # Version 1.0 # License GPL v3 #to do #"gamma", "lgamma", "digamma", "trigamma") setMethod("log", signature(x="SpatRaster"), function(x, base=exp(1)){ opt <- spatOptions() if (base == exp(1)) { x@ptr <- x@ptr$math("log", opt) } else if (base == 2) { x@ptr <- x@ptr$math("log2", opt) } else if (base == 10) { x@ptr <- x@ptr$math("log10", opt) } else { x <- app(x, function(i) log(i, base)) } x } ) #? "gamma", "lgamma", "digamma", "trigamma" setMethod("Math", signature(x="SpatRaster"), function(x){ oper <- as.vector(.Generic)[1] opt <- spatOptions() if (substr(oper, 1, 3) == "cum") { x@ptr <- x@ptr$cum(substr(oper, 4, 10), FALSE, "", FALSE) } else if (oper %in% c("acos", "acosh", "asin", "asinh", "atan", "atanh", "cos", "cosh", "cospi", "sin", "sinh", "sinpi", "tan", "tanh", "tanpi")) { x@ptr <- x@ptr$trig(oper, opt) } else { x@ptr <- x@ptr$math(oper, opt) } messages(x, oper) } ) setMethod("math", signature(x="SpatRaster"), function(x, fun, digits=0, filename="", overwrite=FALSE, ...){ if (!is.character(fun)) { error("math", "fun must be a character value") } fun = fun[1] opt <- spatOptions(filename, overwrite, ...) if (substr(fun, 1, 3) == "cum") { x@ptr <- x@ptr$cum(substr(fun, 4, 10), FALSE, "", FALSE) } else if (fun %in% c("acos", "acosh", "asin", "asinh", "atan", "atanh", "cos", "cosh", "cospi", "sin", "sinh", "sinpi", "tan", "tanh", "tanpi")) { x@ptr <- x@ptr$trig(fun, opt) } else if (fun %in% c("abs", "sign", "sqrt", "ceiling", "floor", "trunc", "log", "log10", "log2")) { x@ptr <- x@ptr$math(fun, opt) } else if (fun %in% c("round", "signif")) { x@ptr <- x@ptr$math2(fun, digits, opt) } else { error("math", "unknown function") } messages(x, fun) } ) setMethod("Math2", signature(x="SpatRaster"), function(x, digits=0){ opt <- spatOptions() oper <- as.vector(.Generic)[1] x@ptr <- x@ptr$math2(oper, digits, opt) messages(x, oper) } ) setMethod("Math", signature(x="SpatExtent"), function(x){ oper <- as.vector(.Generic)[1] if (oper == "floor") { x@ptr <- x@ptr$floor() } else if (oper == "ceiling") { x@ptr <- x@ptr$ceil() } else { error(oper, "not implemented for SpatExtent") } if (!x@ptr$valid) { error(oper, "invalid extent") } return(x) } ) setMethod("Math2", signature(x="SpatExtent"), function(x, digits=0){ oper <- as.vector(.Generic)[1] if (oper == "round") { x@ptr <- x@ptr$round(digits) if (!x@ptr$valid) { error(oper, "invalid extent") } return(x) } else { error(oper, "not implemented for SpatExtent") } } ) setMethod("Math2", signature(x="SpatVector"), function(x, digits=4){ oper <- as.vector(.Generic)[1] if (oper == "round") { x@ptr <- x@ptr$round(digits) return(x) } else { error(oper, "not implemented for SpatVector") } } ) terra/R/gdal.R0000644000175000017500000000564114201035747012765 0ustar nileshnilesh fileBlocksize <- function(x) { v <- x@ptr$getFileBlocksize() m <- matrix(v, ncol=2) colnames(m) <- c("rows", "cols") m } gdalCache <- function(size=NA) { if (is.na(size)) { .getGDALCacheSizeMB() } else { if (size > 0) { .setGDALCacheSizeMB(size) } } } gdal <- function(warn=NA, drivers=FALSE, lib="gdal") { if (!is.na(warn)) { warn <- as.integer(warn) stopifnot(warn %in% c(1:4)) .set_gdal_warnings(warn) } else if (drivers) { x <- .gdaldrivers() x <- do.call(cbind, x) x[,2] = c("vector", "raster")[as.integer(x[,2])+1] #x[,3] = c("read", "read/copy-write", "read/write")[as.integer(x[,3])+1] x[,3] = c("read", "read/write", "read/write")[as.integer(x[,3])+1] colnames(x) <- c("name", "type", "can", "vsi", "long.name") x <- data.frame(x) x[,4] <- x[,4] == 1 x <- x[order(x$type, x$name), ] rownames(x) <- NULL x } else { lib <- tolower(lib) if (lib=="gdal") { .gdal_version() } else if (lib=="proj") { proj_version() } else if (lib=="geos") { .geos_version() } else { c(gdal=.gdal_version(), proj=proj_version(), geos=.geos_version()) } } } .describe_sds <- function(x, print=FALSE) { x <- .sdinfo(x) if (length(x[[1]]) == 1 & length(x[[2]]) == 0) { error("gdal (sds)", x[[1]]) } names(x) <- c("name", "var", "desc", "nrow", "ncol", "nlyr") m <- do.call(cbind, x) m <- data.frame(id=1:nrow(m), m, stringsAsFactors=FALSE) ii <- which(colnames(m) %in% c("nrow", "ncol", "nlyr")) for (i in ii) m[,i] <- as.integer(m[,i]) if (print) { print(m) invisible(m) } else { m } } .meta_sds <- function(x, parse=FALSE, ...) { if (parse) { m <- .parsedsdsmetadata(x) m <- do.call(cbind, m) if (nrow(m) > 0) { m <- data.frame(1:nrow(m), m, stringsAsFactors=FALSE) } else { m <- data.frame(0[0], m, stringsAsFactors=FALSE) } for (i in 5:7) m[,i] <- as.integer(m[,i]) colnames(m) <- c("id", "name", "var", "desc", "nrow", "ncol", "nlyr") } else { m <- .sdsmetadata(x) } m } setMethod("describe", signature(x="character"), function(x, sds=FALSE, meta=FALSE, parse=FALSE, options="", print=FALSE, open_opt="") { if (meta) { if (sds) { return(.meta_sds(x, parse)) } else { return(.metadata(x)) } } if (sds) { return(.describe_sds(x, print=print)) } options <- unique(trimws(options)) options <- options[options != ""] if (length(options) > 0) { options <- paste0("-", options) options <- gsub("^--", "-", options) } open_opt <- unique(trimws(open_opt)) open_opt <- open_opt[open_opt != ""] g <- .gdalinfo(x, options, open_opt) if (g == "") { add <- ifelse(!file.exists(x), "\n", "\nThe file does not exist\n") x <- paste0("GDAL cannot open: ", x, add) } y <- unlist(strsplit(g, "\n")) if (print) { cat(g, "\n") invisible(y) } else { return(y) } } ) terra/R/dimensions.R0000644000175000017500000000630314201035747014222 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : June 2017 # Version 0.9 # License GPL v3 setMethod("dim", signature(x="SpatRaster"), function(x){ return(c(nrow(x), ncol(x), nlyr(x))) } ) setMethod("dim", signature(x="SpatRasterDataset"), function(x) { dim(x[1])[1:2] } ) setMethod("nrow", signature(x="SpatRaster"), function(x){ return(x@ptr$nrow())} ) setMethod("nrow", signature(x="SpatRasterDataset"), function(x){ return(x[1]@ptr$nrow())} ) setMethod("nrow", signature(x="SpatVector"), function(x){ return(x@ptr$nrow())} ) setMethod("ncol", signature(x="SpatRaster"), function(x){ return(x@ptr$ncol()) } ) setMethod("ncol", signature(x="SpatRasterDataset"), function(x){ return(x[1]@ptr$ncol())} ) setMethod("ncol", signature(x="SpatVector"), function(x){ return(x@ptr$ncol())} ) setMethod("dim<-", signature(x="SpatRaster"), function(x, value) { if (length(value) == 1) { value <- c(value, ncol(x), nlyr(x)) } else if (length(value) == 2) { value <- c(value, nlyr(x)) } else if (length(value) > 3) { warn("dim<-", "value should have length 1, 2, or 3. Additional values ignored") value <- value[1:3] } value <- as.integer(pmax(round(value), c(1,1,1))) #here we lose all attributes rast(nrows=value[1], ncols=value[2], nlyrs=value[3], extent=ext(x), crs=crs(x)) } ) setMethod("ncell", signature(x="SpatRaster"), function(x) { return(as.numeric(ncol(x)) * nrow(x)) } ) setMethod("ncell", signature(x="SpatRasterDataset"), function(x) { ncell(x[1]) } ) setMethod("ncell", signature(x="ANY"), function(x) { NROW(x) * NCOL(x) } ) setMethod("size", signature(x="SpatRaster"), function(x) { x@ptr$size() } ) setMethod("nlyr", signature(x="SpatRaster"), function(x){ return(x@ptr$nlyr() ) } ) setMethod("nlyr", signature(x="SpatRasterDataset"), function(x){ sapply(1:length(x), function(i) nlyr(x[i])) } ) setMethod("nsrc", signature(x="SpatRaster"), function(x){ return(x@ptr$nsrc() ) } ) .nlyrBySource <- function(x) { x@ptr$nlyrBySource(); } setMethod("ncol<-", signature("SpatRaster", "numeric"), function(x, value) { dim(x) <- c(nrow(x), value) return(x) } ) setMethod("nrow<-", signature("SpatRaster", "numeric"), function(x, value) { dim(x) <- c(value, ncol(x)) return(x) } ) setMethod("nlyr<-", signature("SpatRaster", "numeric"), function(x, value) { dim(x) <- c(nrow(x), ncol(x), value) return(x) } ) setMethod("res", signature(x="SpatRaster"), function(x) { x@ptr$res } ) setMethod("res", signature(x="SpatRasterDataset"), function(x) { x[1]@ptr$res } ) setMethod("res<-", signature(x="SpatRaster"), function(x, value) { if (length(value) == 1) { value <- c(value, value) } else if (length(value) > 2) { warn("res<-", "value should have length 1 or 2. Additional values ignored") } x@ptr <- x@ptr$set_resolution(value[1], value[2]) messages(x, "resolution") } ) setMethod("xres", signature(x="SpatRaster"), function(x) { res(x)[1] } ) setMethod("yres", signature(x="SpatRaster"), function(x) { res(x)[2] } ) terra/R/app.R0000644000175000017500000001660114201035747012634 0ustar nileshnilesh .cpp_funs <- c("sum", "mean", "median", "modal", "which", "which.min", "which.max", "min", "max", "prod", "any", "all", "sd", "std", "first") setMethod("sapp", signature(x="SpatRaster"), function(x, fun, ..., filename="", overwrite=FALSE, wopt=list()) { #x <- lapply(as.list(x), fun, ..., wopt=wopt) #x <- lapply(x, messages) #x <- rast(x) x <- rast(lapply(as.list(x), function(i, ...) messages(fun(i, ..., wopt=wopt)))) if (filename != "") { writeRaster(x, filename, overwrite, wopt=wopt) } else { tighten(x) } } ) setMethod("app", signature(x="SpatRaster"), function(x, fun, ..., cores=1, filename="", overwrite=FALSE, wopt=list()) { txtfun <- .makeTextFun(fun) if (inherits(txtfun, "character")) { if (txtfun %in% .cpp_funs) { opt <- spatOptions(filename, overwrite, wopt=wopt) na.rm <- isTRUE(list(...)$na.rm) x@ptr <- x@ptr$summary(txtfun, na.rm, opt) return(messages(x, "app")) } } fun <- match.fun(fun) out <- rast(x) nlyr(out) <- 1 nc <- ncol(x) readStart(x) on.exit(readStop(x)) nl <- nlyr(x) dots <- list(...) if (length(dots) > 0) { test <- any(sapply(dots, function(i) inherits(i, "SpatRaster"))) if (test) { error("app", "additional arguments cannot be a SpatRaster") } } # figure out the shape of the output by testing with up to 13 cells teststart <- max(1, 0.5 * nc - 6) testend <- min(teststart + 12, nc) ntest <- 1 + testend - teststart v <- readValues(x, round(0.51*nrow(x)), 1, teststart, ntest, mat=TRUE) usefun <- FALSE if (nl==1) { r <- fun(v, ...) usefun <- TRUE } else { r <- try(apply(v, 1, fun, ...), silent=TRUE) if (inherits(r, "try-error")) { rr <- try(fun(v, ...), silent=TRUE) if (inherits(rr, "try-error")) { error("app", paste0("cannot use this function\n", attr(r, "condition"))) } else { usefun <- TRUE r <- rr } } } if (is.list(r)) { if (length(unique(sapply(r, length))) > 1) { error("app", "'fun' returns a list (should be numeric or matrix).\nPerhaps because returned values have different lengths due to NAs in input?") } else { error("app", "'fun' returns a list (should be numeric or matrix)") } } trans <- FALSE if (NCOL(r) > 1) { #? if ((ncol(r) %% ntest) == 0) { if (ncol(r) == ntest) { nlyr(out) <- nrow(r) trans <- TRUE nms <- rownames(r) } else if (nrow(r) == ntest) { nlyr(out) <- ncol(r) nms <- colnames(r) } else { error("app", "the number of values returned by 'fun' is not appropriate\n(it should be the product of the number of cells and and a positive integer)") } if (is.null(wopt$names)) { wopt$names <- nms } } else { if ((length(r) %% ntest) != 0) { error("app", "the number of values returned by 'fun' is not appropriate") } else { nlyr(out) <- length(r) / ntest } } doclust <- FALSE if (inherits(cores, "cluster")) { doclust <- TRUE ncores <- length(cores) } else if (cores > 1) { doclust <- TRUE ncores <- cores cores <- parallel::makeCluster(cores) on.exit(parallel::stopCluster(cores), add=TRUE) } ncops <- nlyr(x) / nlyr(out) ncops <- ifelse(ncops > 1, ceiling(ncops), 1) * 4 b <- writeStart(out, filename, overwrite, wopt=wopt, n=ncops) if (doclust) { for (i in 1:b$n) { v <- readValues(x, b$row[i], b$nrows[i], 1, nc, TRUE) icsz <- max(min(100, ceiling(b$nrows[i] / ncores)), b$nrows[i]) r <- parallel::parRapply(cores, v, fun, ..., chunk.size=icsz) if (nlyr(out) > 1) { r <- matrix(r, ncol=nlyr(out), byrow=TRUE) } writeValues(out, r, b$row[i], b$nrows[i]) } } else { if (usefun) { for (i in 1:b$n) { v <- readValues(x, b$row[i], b$nrows[i], 1, nc, TRUE) r <- fun(v, ...) if (trans) { r <- t(r) } writeValues(out, r, b$row[i], b$nrows[i]) } } else { for (i in 1:b$n) { v <- readValues(x, b$row[i], b$nrows[i], 1, nc, TRUE) r <- apply(v, 1, fun, ...) if (trans) { r <- t(r) #r <- as.vector(r) } writeValues(out, r, b$row[i], b$nrows[i]) } } } writeStop(out) } ) .app_test_stack <- function(v, fun, ncols, ...) { # figure out the shape of the output nms = "" nr <- nrow(v[[1]]) v <- lapply(v, as.vector) v <- do.call(cbind, v) r <- apply(v, 1, fun, ...) if (inherits(r, "try-error")) { nl <- -1 } trans <- FALSE if (NCOL(r) > 1) { #? if ((ncol(r) %% nc) == 0) { if (ncol(r) == ncols) { nl <- nrow(r) trans <- TRUE } else if (nrow(r) == ncols) { nl <- ncol(r) } else { error("app", "cannot handle 'fun'") } } else if (length(r) >= nr) { if ((length(r) %% nr) == 0) { nl <- length(r) / nr } else { nl <- -1 } } else { nl <- -1 } if (is.matrix(r)) { nms <- colnames(r) } list(nl=nl, trans=trans, names=nms) } .app_test_stack <- function(v, fun, ncols, ...) { # figure out the shape of the output nms = "" nr <- nrow(v[[1]]) v <- lapply(v, as.vector) v <- do.call(cbind, v) r <- apply(v, 1, fun, ...) if (inherits(r, "try-error")) { nl <- -1 } trans <- FALSE if (NCOL(r) > 1) { #? if ((ncol(r) %% nc) == 0) { if (ncol(r) == ncols) { nl <- nrow(r) trans <- TRUE } else if (nrow(r) == ncols) { nl <- ncol(r) } else { error("app", "'fun' is not appropriate") } } else if (length(r) >= nr) { if ((length(r) %% nr) == 0) { nl <- length(r) / nr } else { nl <- -1 } } else { nl <- -1 } if (is.matrix(r)) { nms <- colnames(r) } list(nl=nl, trans=trans, names=nms) } setMethod("app", signature(x="SpatRasterDataset"), function(x, fun, ..., cores=1, filename="", overwrite=FALSE, wopt=list()) { txtfun <- .makeTextFun(match.fun(fun)) if (inherits(txtfun, "character")) { if (txtfun %in% .cpp_funs) { opt <- spatOptions(filename, overwrite, wopt=wopt) narm <- isTRUE(list(...)$na.rm) r <- rast() r@ptr <- x@ptr$summary(txtfun, narm, opt) return (messages(r, "app") ) } } if (missing(fun)) error("app", "'fun' is missing") ncx <- ncol(x[1]) nrx <- nrow(x[1]) readStart(x) on.exit(readStop(x)) v <- lapply(1:length(x), function(i) readValues(x[i], round(0.51*nrx), 1, 1, ncx, mat=TRUE)) test <- .app_test_stack(v, fun, ncx, ...) if (test$nl < 1) error("app", "cannot find 'fun'") out <- rast(x[1], nlyrs=test$nl) if (length(test$names == test$nl)) { if (is.null(wopt$names)) wopt$names <- test$names } nc <- (nlyr(x[1]) * length(x)) / nlyr(out) nc <- ifelse(nc > 1, ceiling(nc), 1) * 3 b <- writeStart(out, filename, overwrite, wopt=wopt, n=nc) if (cores > 1) { cls <- parallel::makeCluster(cores) on.exit(parallel::stopCluster(cls), add=TRUE) for (i in 1:b$n) { v <- lapply(1:length(x), function(s) as.vector(readValues(x[s], b$row[i], b$nrows[i], 1, ncx, mat=TRUE))) v <- do.call(cbind, v) icsz <- max(min(100, ceiling(b$nrows[i] / cores)), b$nrows[i]) r <- parallel::parRapply(cls, v, fun, ..., chunk.size=icsz) if (test$trans) { r <- t(r) } writeValues(out, r, b$row[i], b$nrows[i]) } } else { for (i in 1:b$n) { v <- lapply(1:length(x), function(s) as.vector(readValues(x[s], b$row[i], b$nrows[i], 1, ncx, mat=TRUE))) r <- apply(do.call(cbind, v), 1, fun, ...) if (test$trans) { r <- t(r) } writeValues(out, r, b$row[i], b$nrows[i]) } } #readStop(x) writeStop(out) } ) terra/R/hist.R0000644000175000017500000000430214201035747013016 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : June 2008 # Version 1.0 # License GPL v3 setMethod("hist", signature(x="SpatRaster"), function(x, layer, maxcell=1000000, plot=TRUE, main, ...) { if (missing(layer)) { y <- 1:nlyr(x) } else if (is.character(layer)) { y <- match(layer, names(x)) } else { y <- layer } y <- unique(as.integer(round(y))) y <- stats::na.omit(y) y <- y[ y >= 1 & y <= nlyr(x) ] nl <- length(y) if (nl == 0) { error("hist", "no layers selected") } if (missing(main)) { main=names(x) } if (nl > 1) { res <- list() if (nl > 16) { warn("hist", "only the first 16 layers are plotted") nl <- 16 y <- y[1:16] } nc <- ceiling(sqrt(nl)) nr <- ceiling(nl / nc) mfrow <- graphics::par("mfrow") spots <- mfrow[1] * mfrow[2] if (spots < nl) { old.par <- graphics::par(no.readonly =TRUE) on.exit(graphics::par(old.par)) graphics::par(mfrow=c(nr, nc)) } for (i in 1:length(y)) { res[[i]] = .hist1(x[[ y[i] ]], maxcell=maxcell, main=main[y[i]], plot=plot, ...) } } else if (nl==1) { if (nlyr(x) > 1) { x <- x[[y]] main <- main[y] } res <- .hist1(x, maxcell=maxcell, main=main, plot=plot, ...) } if (plot) { return(invisible(res)) } else { return(res) } } ) .hist1 <- function(x, maxcell, main, plot, ...){ stopifnot(hasValues(x)) if ( ncell(x) <= maxcell ) { v <- stats::na.omit(values(x)) } else { # TO DO: make a function that does this by block and combines all data into a single histogram v <- spatSample(x, maxcell, method="regular", as.df=FALSE, as.raster=FALSE) msg <- paste("a sample of", round(100 * length(v) / ncell(x)), "% of the cells was used", sep="") if (any(is.na(v))) { v <- stats::na.omit(v) msg <- paste(msg, " (of which ", 100 - round(100 * length(v) / maxcell ), "% was NA)", sep="") } warn("hist", msg) } if (nrow(v) == 0) { error("hist", "all (sampled) values are NA") } # if (.shortDataType(x) == 'LOG') { # v <- v * 1 # } if (plot) { hist(v, main=main, plot=plot, ...) } else { hist(v, plot=plot, ...) } } terra/R/selectHigh.R0000644000175000017500000000035514201035747014132 0ustar nileshnilesh setMethod("selectHighest", signature(x="SpatRaster"), function(x, n, low=FALSE) { x <- x[[1]] n <- min(ncell(x), max(1, n)) i <- order(values(x, mat=FALSE), decreasing=!low)[1:n] x <- rast(x) x[i] <- 1 x } ) terra/R/spatvec.R0000644000175000017500000000742414202373722013523 0ustar nileshnilesh setMethod("geomtype", signature(x="SpatVector"), function(x){ x@ptr$type() } ) setMethod("geomtype", signature(x="SpatVectorProxy"), function(x){ x@ptr$v$type() } ) setMethod("datatype", signature(x="SpatVector"), function(x){ x@ptr$df$get_datatypes() } ) setMethod("is.lines", signature(x="SpatVector"), function(x) { geomtype(x) == "lines" } ) setMethod("is.polygons", signature(x="SpatVector"), function(x) { geomtype(x) == "polygons" } ) setMethod("is.points", signature(x="SpatVector"), function(x) { grepl("points", geomtype(x)) } ) setMethod("geomtype", signature(x="Spatial"), function(x){ type <- sub("spatial", "", as.vector(tolower(class(x)))) type <- sub("dataframe", "", type) if (type %in% c("grid", "pixels")) type <- "raster" type } ) setMethod("geom", signature(x="SpatVector"), function(x, wkt=FALSE, hex=FALSE, df=FALSE){ if (hex) { x@ptr$hex() } else if (wkt) { x@ptr$getGeometryWKT() # or via geos with # x@ptr$wkt() } else { g <- x@ptr$get_geometry() g <- do.call(cbind, g) colnames(g) <- c("geom", "part", "x", "y", "hole")[1:ncol(g)] if (df) { data.frame(g) } else { g } } } ) setMethod("crds", signature(x="SpatVector"), function(x, df=FALSE){ g <- x@ptr$coordinates() g <- do.call(cbind, g) colnames(g) <- c("x", "y") if (df) { data.frame(g) } else { g } } ) setMethod("crds", signature(x="SpatRaster"), function(x, df=FALSE, na.rm=TRUE){ x <- as.points(x, na.rm=na.rm) crds(x, df=df) } ) setMethod("dim", signature(x="SpatVector"), function(x){ c(nrow(x), ncol(x)) } ) setMethod("dim", signature(x="SpatVectorProxy"), function(x){ c(x@ptr$v$geom_count, x@ptr$v$ncol()) } ) as.data.frame.SpatVector <- function(x, row.names=NULL, optional=FALSE, geom=NULL, ...) { d <- .getSpatDF(x@ptr$df, ...) # fix empty names colnames(d) <- x@ptr$names if (!is.null(geom)) { geom <- match.arg(toupper(geom), c("WKT", "HEX", "XY")) if (geom == "XY") { if (!grepl("points", geomtype(x))) { error("as.data.frame", 'geom="XY" is only valid for point geometries') } if (nrow(d) > 0) { d <- cbind(d, crds(x)) } else { d <- data.frame(crds(x), ...) } } else { g <- geom(x, wkt=geom=="WKT", hex=geom=="HEX") if (nrow(d) > 0) { d$geometry <- g } else { d <- data.frame(geometry=g, stringsAsFactors=FALSE, ...) } } } d } setMethod("as.data.frame", signature(x="SpatVector"), as.data.frame.SpatVector) get.data.frame <- function(x) { v <- vect() v@ptr <- x@ptr$v d <- as.data.frame(v) d[0,,drop=FALSE] } as.list.SpatVector <- function(x, geom=NULL, ...) { as.list(as.data.frame(x, geom=geom)) } setMethod("as.list", signature(x="SpatVector"), as.list.SpatVector) setMethod ("expanse", "SpatVector", function(x, unit="m", transform=TRUE) { a <- x@ptr$area(unit, transform, double()); x <- messages(x, "expanse"); return(abs(a)) } ) setMethod("perim", signature(x="SpatVector"), function(x) { p <- x@ptr$length(); x <- messages(x, "length"); return(p) } ) setMethod("length", signature(x="SpatVector"), function(x) { x@ptr$size() } ) setMethod("fillHoles", signature(x="SpatVector"), function(x, inverse=FALSE) { if (inverse) { x@ptr <- x@ptr$get_holes() } else { x@ptr <- x@ptr$remove_holes() } messages(x) } ) setMethod("centroids", signature(x="SpatVector"), function(x) { x@ptr <- x@ptr$centroid(TRUE) messages(x) } ) setMethod("densify", signature(x="SpatVector"), function(x, interval, equalize=TRUE) { x@ptr <- x@ptr$densify(interval, equalize) messages(x) } ) terra/R/inset.R0000644000175000017500000000607714201035747013204 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : December 2020 # Version 1.0 # License GPL v3 setMethod("inext", signature(x="SpatVector"), function(x, e, y=NULL, gap=0) { # the area used for scaling gap <- rep_len(gap, 2) e <- as.vector(e) + c(gap[1], -gap[1], gap[2], -gap[2]) stopifnot((e[2] > e[1]) && (e[4] > e[3])) ex <- ext(x) x <- shift(x, e[1] - ex[1], e[3] - ex[3]) ve <- ext(x) fx <- (e[2] - e[1]) / (ve[2] - ve[1]) fy <- (e[4] - e[3]) / (ve[4] - ve[3]) if (!is.null(y)) { y <- shift(y, e[1] - ex[1], e[3] - ex[3]) rescale(y, fx=fx, fy=fy, e[1], e[3]) } else { rescale(x, fx=fx, fy=fy, e[1], e[3]) } } ) .inset <- function(x, e, loc="", scale=0.2, background="white", perimeter="black", pper, box=NULL, pbox, ...) { usr <- graphics::par("usr") if (missing(e)) { e <- ext(usr) r <- diff(e[1:2]) / diff(e[3:4]) e[2] <- e[1] + scale * diff(e[1:2]) e[3] <- e[4] - scale * diff(e[3:4]) * r } offset <- 0.9 #offset <- max(0.1, min(1, offset)) scale <- offset * min(e / ext(x)) y <- rescale(x, scale) ey <- ext(y) xy <- c(mean(ey[1:2]), mean(ey[3:4])) xybox <- c(mean(e[1:2]), mean(e[3:4])) dx <- xybox[1] - xy[1] dy <- xybox[2] - xy[2] y <- shift(y, dx, dy) if (!is.null(box)) { ex <- ext(x) box <- rescale(as.polygons(box), scale, x0=ex[1]+diff(ex[1:2])/2, y0=ex[3]+diff(ex[3:4])/2) box <- shift(box, dx, dy) } if ((loc != "") && (loc != "topleft")) { stopifnot(loc %in% c("bottomright", "bottom", "bottomleft", "left", "topleft", "top", "topright", "right", "center")) ex <- ext(x) if (grepl("top", loc)) { dy <- usr[4] - e[4] } else if (grepl("bottom", loc)) { dy <- usr[3] - e[3] } else { dy <- (usr[3] + diff(usr[3:4])/2) - (e[3] + diff(e[3:4])/2) } if (grepl("left", loc)) { dx <- usr[1] - e[1] } else if (grepl("right", loc)) { dx <- usr[2] - e[2] } else { dx <- (usr[1] + diff(usr[1:2])/2) - (e[1] + diff(e[1:2])/2) } y <- shift(y, dx, dy) e <- shift(e, dx, dy) if (!is.null(box)) { box <- shift(box, dx, dy) } } if (!is.na(background)) { polys(as.polygons(e), col=background, lty=0) } plot(y, ..., axes=FALSE, legend=FALSE, add=TRUE) if (isTRUE(perimeter)) { if (missing(pper) || !is.list(pper)) { pper <- list() } pper$x <- e do.call(lines, pper) #lines(e, col=perimeter) } if (!is.null(box)) { if (missing(pbox) || !is.list(pbox)) { pbox <- list() } pbox$x <- box do.call(lines, pbox) } invisible(y) } setMethod("inset", signature(x="SpatVector"), function(x, e, loc="", scale=0.2, background="white", perimeter=TRUE, box=NULL, pper, pbox, ...) { .inset(x, e, loc=loc, scale=scale, background=background, perimeter=perimeter, pper=pper, box=box, pbox=pbox, ...) } ) setMethod("inset", signature(x="SpatRaster"), function(x, e, loc="", scale=0.2, background="white", perimeter=TRUE, box=NULL, pper, pbox, ...) { .inset(x, e, loc=loc, scale=scale, background=background, perimeter=perimeter, pper=pper, box=box, pbox=pbox, ...) } ) terra/R/rasterize.R0000644000175000017500000001667514201035747014077 0ustar nileshnilesh rasterize_points <- function(x, y, field, values, fun="last", background=NA, update=FALSE, filename="", overwrite=FALSE, wopt=list(), ...) { if (update) { if (!hasValues(y)) { update <- FALSE } else { background <- NA } } nrx <- nrow(x) if (!is.data.frame(values)) { values <- as.data.frame(values) } if (nrow(values) == 1) { values <- sapply(values, function(x) rep_len(x, nrx)) if (!is.data.frame(values)) { # dropped if nrx==1 values <- as.data.frame(values) } } else { if (nrow(values) != nrx) { error("rasterize", "the number or rows in values does not match the number of points") } } nl <- ncol(values) r <- rast(y, nlyrs=nl) # values(r) <- background levs <- list() has_levels <- FALSE for (i in 1:nl) { if (is.character(values[,i])) { f <- as.factor(values[,i]) levs[[i]] <- levels(f) values[,i] <- as.integer(f) - 1 has_levels <- TRUE } } g <- cellFromXY(y, x) i <- which(!is.na(g)) g <- g[i] if (length(g) == 0) { return(r) } values <- values[i,] if (missing(fun)) fun <- "last" if (is.character(fun) && (fun %in% c("first", "last", "pa"))) { narm <- isTRUE(list(...)$na.rm) if (fun == "pa") { if (narm) { values <- aggregate(values, list(g), function(i) length(na.omit(i))) values[values < 1] <- background } else { values <- aggregate(values, list(g), function(i) 1) } has_levels <- FALSE } else if (fun == "first") { if (narm) { values <- aggregate(values, list(g), function(i) na.omit(i)[1]) } else { values <- aggregate(values, list(g), function(i) i[1]) } } else if (fun == "last") { if (narm) { values <- aggregate(values, list(g), function(i) rev(na.omit(i))[1]) } else { values <- aggregate(values, list(g), function(i) rev(i)[1]) } } #r[values[,1]] <- as.matrix(values[,-1]) } else { has_levels <- FALSE values <- aggregate(values, list(g), fun, ...) # allow for multiple fields #r[a[,1]] <- as.matrix(a[,-1]) levs <- NULL } if (!update) { if (has_levels) { levels(r) <- levs } b <- writeStart(r, filename=filename, overwrite=overwrite, wopt=wopt) filename <- "" } else { b <- writeStart(r, "") } nc <- ncol(r) for (i in 1:b$n) { w <- matrix(background, nrow=b$nrows * nc, ncol=nl) mincell <- cellFromRowCol(r, b$row[i], 1) maxcell <- cellFromRowCol(r, b$row[i] + b$nrows[i]-1, nc) vv <- values[values[,1] >= mincell & values[,1] <= maxcell, ] if (nrow(vv) > 0) { vv[,1] <- vv[,1] - (b$row[i] - 1) * nc w[vv[,1],] <- vv[,-1] } writeValues(r, w, b$row[i], b$nrows[i]) } r <- writeStop(r) if (update) { r <- cover(r, y, filename=filename, overwrite=overwrite, wopt=wopt) } return (r) } setMethod("rasterize", signature(x="matrix", y="SpatRaster"), function(x, y, values=1, fun, ..., background=NA, update=FALSE, filename="", overwrite=FALSE, wopt=list()) { lonlat <- .checkXYnames(colnames(x)) rasterize_points(x=x, y=y, field="", values=rep_len(values, nrow(x)), fun=fun, background=background, update=update, filename=filename, overwrite=overwrite, wopt=wopt, ...) } ) setMethod("rasterize", signature(x="SpatVector", y="SpatRaster"), function(x, y, field="", fun, ..., background=NA, touches=FALSE, update=FALSE, sum=FALSE, cover=FALSE, filename="", overwrite=FALSE, wopt=list()) { values <- 1 if (is.null(field) || is.na(field) || (field == "")) { field <- "" } else if (!is.character(field)) { values <- as.numeric(field) field <- "" } else { stopifnot(field %in% names(x)) } g <- geomtype(x) if (grepl("points", g)) { nrx <- nrow(x) # also allow for multiple columns to multiple layers if (field[1] != "") { values <- x[[field]] } x <- crds(x) if (nrow(x) != nrx) { # multi-points values <- sapply(1:ncol(values), function(i) values[g[,1], i]) } return( rasterize_points(x=x, y=y, field=field, values=values, fun=fun, background=background, update=update, filename=filename, overwrite=overwrite, wopt=wopt, ...) ) } opt <- spatOptions(filename, overwrite, wopt=wopt) pols <- grepl("polygons", g) if (cover[1] && pols) { y@ptr <- y@ptr$rasterize(x@ptr, "", 1, background, touches[1], sum[1], TRUE, FALSE, TRUE, opt) } else { background <- as.numeric(background[1]) y@ptr <- y@ptr$rasterize(x@ptr, field, values, background, touches[1], sum[1], FALSE, update[1], TRUE, opt) } messages(y, "rasterize") } ) # old_rasterize <- function(x, y, field, fun, background=NA, update=FALSE, touches=is.lines(x), cover=FALSE, filename="", ...) { # g <- geomtype(x) # if (grepl("points", g)) { # r <- rasterize_points(x=x, y=y, field=field, fun=fun, background=background, update=update, filename=filename, ...) # return (r) # } # opt <- spatOptions(filename, ...) # if (cover[1] && grepl("polygons", g)) { # y@ptr <- y@ptr$rasterize1(x@ptr, "", 1, "", background, FALSE, touches[1], FALSE, TRUE, opt) # y <- messages(y, "rasterize") # return(y) # } # if (missing(field)) field <- 1:nrow(x) # domask <- FALSE # if (any(is.na(field))) { # if (length(field) == 1) { # y <- mask(y, x, inverse=FALSE, updatevalue=NA, touches=touches, filename=filename, ...) # return (y) # } else if (length(field) == nrow(x)) { # i <- is.na(field) # x <- x[!i, ] # if (update & !is.na(background)) { # xx <- x[i, ] # domask <- TRUE # fname <- filename # filename <- "" # } # } else { # error("rasterize", "NA detected in field, but length is not 1 or nrow(x)") # } # } # levs <- ""[0] # inverse <- FALSE # use "mask" for TRUE # background <- as.numeric(background[1]) # #if (is.na(background)) background = 0/0 # NAN # if (is.numeric(field)) { # if ((length(field) == 1) && (ncol(x) > 1)) { # if (field > 0 && field <= ncol(x)) { # field <- names(x)[field] # } else { # error("rasterize", "field index outside the value range (1:ncol(x))") # } # } else { # y@ptr <- y@ptr$rasterize1(x@ptr, "", field, levs, background, update[1], touches[1], inverse[1], FALSE, opt) # } # } # if (is.character(field)) { # if (length(field) == 1) { # i <- which(field == names(x)) # if (length(i) == 0) { # error("rasterize", paste0(field, " is not a valid fieldname")) # } # dtype <- datatype(x)[i] # if (dtype == "string") { # v <- x[[field]][,1] # f <- as.factor(v) # levs <- levels(f) # v <- as.integer(f) - 1 # y@ptr <- y@ptr$rasterize1(x@ptr, field, v, levs, background, update[1], touches[1], inverse[1], FALSE, opt) # } else { # #y@ptr <- y@ptr$rasterize1(x@ptr, field, 0[0], levs, background, update[1], touches[1], inverse[1], opt) # ## for old gdal # y@ptr <- y@ptr$rasterize1(x@ptr, field, x[[field,drop=T]], levs, background, update[1], touches[1], inverse[1], FALSE, opt) # } # } else { # f <- as.factor(field) # levs <- levels(f) # field <- as.integer(f) - 1 # y@ptr <- y@ptr$rasterize1(x@ptr, "value", field, levs, background, update[1], touches[1], inverse[1], FALSE, opt) # } # } # if (domask) { # y <- mask(y, xx, inverse=FALSE, updatevalue=NA, touches=touches, filename=fname, overwrite=overwrite, ...) # return (y) # } # messages(y, "rasterize") # } terra/R/aggregate.R0000644000175000017500000002130114202045120013756 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : December 2017 # Version 1.0 # License GPL v3 .makeTextFun <- function(fun) { if (!inherits(fun, "character")) { fun <- match.fun(fun) if (is.primitive(fun)) { test <- try(deparse(fun)[[1]], silent=TRUE) test <- gsub('.Primitive\\(\"', "", test) test <- gsub('\")', "", test) if (test %in% c("sum", "min", "max", "prod", "any", "all")) return(test); } else { depf <- deparse(fun) test1 <- isTRUE(try( depf[2] == 'UseMethod(\"mean\")', silent=TRUE)) test2 <- isTRUE(try( fun@generic == "mean", silent=TRUE)) if (test1 | test2) { return("mean") } test1 <- isTRUE(try( depf[2] == 'UseMethod(\"median\")', silent=TRUE)) test2 <- isTRUE(try( fun@generic == "median", silent=TRUE)) if (test1 | test2) { return("median") } test1 <- isTRUE(try( depf[1] == "function (x, na.rm = FALSE) ", silent=TRUE)) test2 <- isTRUE(try( depf[2] == "sqrt(var(if (is.vector(x) || is.factor(x)) x else as.double(x), ", silent=TRUE)) test3 <- isTRUE(try( depf[3] == " na.rm = na.rm))", silent=TRUE)) if (test1 && test2 && test3) { return("sd") } if (isTRUE(try( fun@generic == "which.min", silent=TRUE))) { return("which.min") } if (isTRUE(try( fun@generic == "which.max", silent=TRUE))) { return("which.max") } if (isTRUE(depf[3] == " wh <- .Internal(which(x))")) return("which") } } return(fun) } setMethod("aggregate", signature(x="SpatRaster"), function(x, fact=2, fun="mean", ..., cores=1, filename="", overwrite=FALSE, wopt=list()) { fun <- .makeTextFun(fun) toc <- FALSE if (inherits(fun, "character")) { if (fun %in% c("sum", "mean", "min", "max", "median", "modal", "sd", "sdpop")) { toc <- TRUE } else { fun <- match.fun(fun) } } else { fun <- match.fun(fun) } if (!hasValues(x)) { toc = TRUE } if (toc) { # fun="mean", expand=TRUE, na.rm=TRUE, filename="" narm <- isTRUE(list(...)$na.rm) opt <- spatOptions(filename, overwrite, wopt=wopt) x@ptr <- x@ptr$aggregate(fact, fun, narm, opt) return (messages(x, "aggregate")) } else { out <- rast(x) nl <- nlyr(out) opt <- spatOptions() out@ptr <- out@ptr$aggregate(fact, "sum", TRUE, opt) out <- messages(out, "aggregate") dims <- x@ptr$get_aggregate_dims(fact) vtest <- values(x, dataframe=TRUE, row=1, nrows=dims[1], col=1, ncols=dims[2]) vtest <- as.list(vtest) test <- sapply(vtest, fun) dm <- dim(test) do_transpose = FALSE if (!is.null(dm)) { do_transpose = TRUE } if (inherits(test, "list")) { error("aggregate", "fun returns a list") } fun_ret <- 1 if (length(test) > nl) { if ((length(test) %% nl) == 0) { fun_ret <- length(test) / nl nlyr(out) <- nlyr(x) * fun_ret } else { error("aggregate", "cannot use this function") } } b <- blockSize(x, 4) nr <- max(1, floor(b$nrows[1] / fact[1])) * fact[1] nrs <- rep(nr, floor(nrow(x)/nr)) d <- nrow(x) - sum(nrs) if (d > 0) nrs <- c(nrs, d) b$row <- c(0, cumsum(nrs))[1:length(nrs)] + 1 b$nrows <- nrs b$n <- length(nrs) outnr <- ceiling(b$nrows / fact[1]); outrows <- c(0, cumsum(outnr))[1:length(outnr)] + 1 nc <- ncol(x) if (cores > 1) { doPar <- TRUE cls <- parallel::makeCluster(cores) on.exit(parallel::stopCluster(cls)) #f <- function(v, ...) parallel::parSapply(cls, v, fun, ...) } else { doPar <- FALSE #f <- function(v, ...) sapply(v, fun, ...) } mpl <- prod(dims[5:6]) * fun_ret readStart(x) on.exit(readStop(x)) ignore <- writeStart(out, filename, overwrite, wopt=wopt) if (doPar) { for (i in 1:b$n) { v <- readValues(x, b$row[i], b$nrows[i], 1, nc) v <- x@ptr$get_aggregates(v, b$nrows[i], dims) v <- parallel::parSapply(cls, v, fun, ...) if (length(v) != outnr[i] * mpl) { error("aggregate", "this function does not return the correct number of values") } if (do_transpose) { v <- t(v) } writeValues(out, v, outrows[i], outnr[i]) } } else { for (i in 1:b$n) { v <- readValues(x, b$row[i], b$nrows[i], 1, nc) v <- x@ptr$get_aggregates(v, b$nrows[i], dims) v <- sapply(v, fun, ...) if (length(v) != outnr[i] * mpl) { error("aggregate", "this function does not return the correct number of values") } if (do_transpose) { v <- t(v) } writeValues(out, v, outrows[i], outnr[i]) } } out <- writeStop(out) messages(out, "aggregate") } } ) .agg_uf <- function(i) { u <- unique(i) if (length(u) == 1) { u } else { NA } } aggregate_attributes <- function(d, by, fun=NULL, ...) { i <- sapply(d, is.numeric) i[colnames(d) %in% by] <- FALSE j <- 1:length(by) da <- db <- NULL if (!is.null(fun)) { if (any(i)) { if (is.character(fun)) { f <- match.fun(fun) da <- aggregate(d[, i,drop=FALSE], d[, by, drop=FALSE], f) names(da)[-j] <- paste0(fun, "_", names(da)[-j]) } else { da <- aggregate(d[, i,drop=FALSE], d[, by, drop=FALSE], fun) names(da)[-j] <- paste0("agg_", names(da)[-j]) } } } else { i[] <- FALSE } i[colnames(d) %in% by] <- TRUE if (any(!i)) { db <- aggregate(d[, !i,drop=FALSE], d[, by, drop=FALSE], .agg_uf) db <- db[, colSums(is.na(db)) < nrow(db), drop=FALSE] if (NCOL(da)>1) { da <- merge(da, db, by=by) } else { da <- db } } dn <- aggregate(d[, by[1],drop=FALSE], d[, by, drop=FALSE], length) colnames(dn)[ncol(dn)] = "agg_n" if (NCOL(da)>1) { dn <- merge(da, dn, by=by) } dn } setMethod("aggregate", signature(x="SpatVector"), function(x, by=NULL, dissolve=TRUE, fun="mean", ...) { if (is.null(by)) { x$aggregate_by_variable = 1; x@ptr <- x@ptr$aggregate("aggregate_by_variable", dissolve) x$aggregate_by_variable = NULL; } else { if (is.character(by)) { by <- unique(by) iby <- match(by, names(x)) if (any(is.na(iby))) { bad <- paste(by[is.na(iby)], collapse=", ") error("aggregate", "invalid name(s) in by: ", bad) } } else if (is.numeric(by)) { by <- unique(by) iby <- round(by) if (any((iby < 1) | (iby > ncol(x)))) { bad <- iby[(iby < 1) | (iby > ncol(x))] error("aggregate", "invalid column number in by: ", bad) } } else { error("aggregate", "by should be character or numeric") } d <- as.data.frame(x) mvars <- FALSE if (length(iby) > 1) { cvar <- apply(d[, iby], 1, function(i) paste(i, collapse="_")) by <- basename(tempfile()) values(x) <- NULL x[[by]] <- cvar mvars <- TRUE } else { by <- names(x)[iby] } x@ptr <- x@ptr$aggregate(by, dissolve) messages(x) if (mvars) { d[[by]] <- cvar a <- aggregate_attributes(d, c(by, names(d)[iby]), fun) } else { a <- aggregate_attributes(d, names(d)[iby], fun) } if (any(is.na(d[[by]]))) { # because NaN and NA are dropped i <- nrow(a)+(1:2) a[i,] <- c(NA, NaN) } i <- match(x[[by,drop=TRUE]], a[[by]]) i <- i[!is.na(i)] if (mvars) { a[[by]] <- NULL } values(x) <- a[i,] } x } ) # setMethod("aggregate", signature(x="SpatVector"), # function(x, by=NULL, dissolve=TRUE, fun="mean", ...) { # gt <- geomtype(x) # if (length(by) > 1) { # error("aggregate", "this method can only aggregate by one variable") # } # x <- methods::as(x, "Spatial") # if (is.numeric(by[1])) { # i <- round(by) # if ((i > 0) & (i <= ncol(x))) { # by <- names(x)[i] # } else { # error("aggregate", "invalid column number supplied: ", by) # } # } # r <- aggregate(x, by=by, dissolve=dissolve, ...) # if (!missing(fun) && !missing(by)) { # if (.hasSlot(x, "data")) { # d <- x@data # i <- sapply(d, is.numeric) # i[colnames(d) %in% by] <- FALSE # j <- 1:length(by) # if (any(i)) { # if (is.character(fun)) { # f <- match.fun(fun) # da <- aggregate(d[, i,drop=FALSE], d[, by, drop=FALSE], f) # names(da)[-j] <- paste0(fun, "_", names(da)[-j]) # } else { # da <- aggregate(d[, i,drop=FALSE], d[, by, drop=FALSE], fun) # names(da)[-j] <- paste0("agg_", names(da)[-j]) # } # r <- merge(r, da, by) # } # i[colnames(d) %in% by] <- TRUE # if (any(!i)) { # db <- aggregate(d[, !i,drop=FALSE], d[, by, drop=FALSE], .agg_uf) # db <- db[, colSums(is.na(db)) < nrow(db), drop=FALSE] # if (ncol(db) > 1) { # r <- merge(r, db, by) # } # } # dn <- aggregate(d[, by,drop=FALSE], d[, by, drop=FALSE], length) # colnames(dn)[2] = "agg_n" # r <- merge(r, dn, by) # } # } # vect(r) # } # ) terra/R/xyRowColCell.R0000644000175000017500000000467514201035747014452 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : October 2017 # Version 1.0 # License GPL v3 setMethod("yFromRow", signature(object="SpatRaster", row="numeric"), function(object, row) { object@ptr$yFromRow(row - 1) } ) setMethod(xFromCol, signature(object="SpatRaster", col="numeric"), function(object, col) { object@ptr$xFromCol(col - 1) } ) setMethod(colFromX, signature(object="SpatRaster", x="numeric"), function(object, x) { cols <- object@ptr$colFromX(x) + 1 cols[cols==0] <- NA cols } ) setMethod(rowFromY, signature(object="SpatRaster", y="numeric"), function(object, y) { rows <- object@ptr$rowFromY(y) + 1 rows[rows==0] <- NA rows } ) setMethod(cellFromXY, signature(object="SpatRaster", xy="matrix"), function(object, xy) { stopifnot(ncol(xy) == 2) #.checkXYnames(colnames(xy)) object@ptr$cellFromXY(xy[,1], xy[,2]) + 1 } ) setMethod(cellFromXY, signature(object="SpatRaster", xy="data.frame"), function(object, xy) { stopifnot(ncol(xy) == 2) #.checkXYnames(colnames(xy)) object@ptr$cellFromXY(xy[,1], xy[,2]) + 1 } ) setMethod(cellFromRowCol, signature(object="SpatRaster", row="numeric", col="numeric"), function(object, row, col) { object@ptr$cellFromRowCol(row-1, col-1) + 1 } ) setMethod(cellFromRowColCombine, signature(object="SpatRaster", row="numeric", col="numeric"), function(object, row, col) { object@ptr$cellFromRowColCombine(row-1, col-1) + 1 } ) setMethod(xyFromCell, signature(object="SpatRaster", cell="numeric"), function(object, cell) { xy <- object@ptr$xyFromCell(cell-1) xy <- do.call(cbind, xy) colnames(xy) <- c("x", "y") xy } ) setMethod(yFromCell, signature(object="SpatRaster", cell="numeric"), function(object, cell) { xyFromCell(object, cell)[,2] } ) setMethod(xFromCell, signature(object="SpatRaster", cell="numeric"), function(object, cell) { xyFromCell(object, cell)[,1] } ) setMethod(rowColFromCell, signature(object="SpatRaster", cell="numeric"), function(object, cell) { rc <- object@ptr$rowColFromCell(cell-1) rc <- do.call(cbind, rc) rc[rc < 0] <- NA rc+1 } ) setMethod(rowFromCell, signature(object="SpatRaster", cell="numeric"), function(object, cell) { rowColFromCell(object, cell)[,1] } ) setMethod(colFromCell, signature(object="SpatRaster", cell="numeric"), function(object, cell) { rowColFromCell(object, cell)[,2] } ) terra/R/plot_vector.R0000644000175000017500000003333414201035747014416 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : June 2019 # Version 1.0 # License GPL v3 setMethod("dots", signature(x="SpatVector"), function(x, field, size, ...) { n <- length(x) if (n < 1) return(NULL) #method <- match.arg(tolower(method), c("regular", "random")) if (is.character(field)) { stopifnot(field %in% names(x)) } else { stopifnot(field > 0 && field <= ncol(x)) } stopifnot(is.numeric(x[[field,drop=TRUE]])) field <- x[[field,drop=TRUE]] size <- size[1] stopifnot(size > 0) d <- round(field / size) d[d < 1 | is.na(d)] <- 0 i <- d > 0; if (sum(i) == 0) { error("dots", "'size' is too small") } s <- spatSample(x[i], d[i], method="random") if (.Device != "null device") { try(points(s, ...), silent=TRUE) } invisible(s) } ) .plotLines <- function(x, out, lty=1, lwd=1, ...) { if (nrow(x) == 0) return(out) cols <- out$cols if (is.null(cols)) cols = rep("black", length(x)) g <- geom(x, df=TRUE) g <- split(g, g[,1]) g <- lapply(g, function(x) split(x, x[,2])) #p <- sapply(g, function(x) lapply(x, function(y) lines(y[,3:4], ...)) n <- length(g) lty <- rep_len(lty, n) lwd <- rep_len(lwd, n) for (i in 1:n) { x <- g[[i]] for (j in 1:length(x)) { lines(x[[j]][,3:4], col=out$main_cols[i], lwd=lwd[i], lty=lty[i], ...) } } out$leg$lwd <- lwd out$leg$lty <- lty out } .plotPolygons <- function(x, out, lty=1, lwd=1, density=NULL, angle=45, ...) { if (nrow(x) == 0) return(out) g <- geom(x, df=TRUE) g <- split(g, g[,1]) g <- lapply(g, function(y) split(y, y[,2])) n <- length(g) if (!is.null(out$leg$border)) { out$leg$border <- rep_len(out$leg$border, n) } else { out$leg$border <- NA } if (!is.null(density)) { out$leg$density <- rep_len(density, length(g)) out$leg$angle <- rep_len(angle, n) } out$leg$lty <- rep_len(lty, n) out$leg$lwd <- rep_len(lwd, n) w <- getOption("warn") on.exit(options("warn" = w)) for (i in 1:length(g)) { gg <- g[[i]] for (j in 1:length(gg)) { a <- gg[[j]] if (any(is.na(a))) next if (any(a[,5] > 0)) { a <- split(a, a[,5]) a <- lapply(a, function(i) rbind(i, NA)) a <- do.call(rbind, a ) a <- a[-nrow(a), ] # g[[i]][[1]] <- a } if (!is.null(out$leg$density)) { graphics::polygon(a[,3:4], col=out$main_cols[i], density=out$leg$density[i], angle=out$leg$angle[i], border=NA, lwd=out$leg$lwd[i], lty=out$leg$lty[i], ...) graphics::polypath(a[,3:4], col=NA, rule="evenodd", border=out$leg$border[i], lwd=out$leg$lwd[i], lty=out$leg$lty[i], ...) } else { graphics::polypath(a[,3:4], col=out$main_cols[i], rule = "evenodd", border=out$leg$border[i], lwd=out$leg$lwd[i], lty=out$leg$lty[i], ...) } } options("warn" = -1) } invisible(out) } .vplot <- function(x, out, xlab="", ylab="", cex=1, pch=20, ...) { if (out$leg$geomtype == "points") { points(x, col=out$main_cols, cex=cex, pch=pch, ...) #if (!out$add) { # e <- out$lim #} out$leg$pch = pch out$leg$pt.cex = cex } else { #e <- matrix(as.vector(ext(x)), 2) if (out$leg$geomtype == "polygons") { out <- .plotPolygons(x, out, density=out$leg$density, angle=out$leg$angle, ...) } else { out <- .plotLines(x, out, ...) } } out } .getCols <- function(n, cols, alpha=1) { if (!is.null(cols)) { ncols <- length(cols) if (ncols > n) { steps <- ncols/n i <- round(seq(1, ncols, steps)) cols <- cols[i] } else if (ncols < n) { cols <- rep_len(cols, n) } } if (alpha < 1 && alpha >= 0) { cols <- grDevices::rgb(t(grDevices::col2rgb(cols)), alpha=alpha[1]*255, maxColorValue=255) } cols } .vect.legend.none <- function(out) { #if (out$leg$geomtype == "points") { out$main_cols <- .getCols(out$ngeom, out$cols, 1) #} else { # out$cols <- .getCols(out$ngeom, out$cols) #} out } .vect.legend.classes <- function(out) { if (isTRUE(out$legend_sort)) { out$uv <- sort(out$uv) } ucols <- .getCols(length(out$uv), out$cols, 1) i <- match(out$v, out$uv) out$cols <- ucols out$main_cols <- ucols[i] if (!is.null(out$colNA)) { out$main_cols[is.na(out$main_cols)] <- out$colNA } out$levels <- out$uv out$leg$legend <- out$uv nlevs <- length(out$uv) cols <- out$cols ncols <- length(cols) if (nlevs < ncols) { i <- trunc((ncols / nlevs) * 1:nlevs) cols <- cols[i] } else { cols <- rep_len(cols, nlevs) } out$leg$fill <- cols out$legend_type <- "classes" if (is.null(out$leg$x)) { # && is.null(out$leg$ext)) { out$leg$x <- "top" } out } .vect.legend.continuous <- function(out) { z <- stats::na.omit(out$v) n <- length(z) if (n == 0) error("plot", "no values") if (!is.numeric(out$v)) { out$v <- as.integer(as.factor(out$v)) z <- stats::na.omit(out$v) n <- length(z) } #out$range <- range(z) interval <- (out$range[2]-out$range[1])/(length(out$cols)-1) breaks <- out$range[1] + interval * (0:(length(out$cols)-1)) out$legend_type <- "continuous" if (is.null(out$levels)) { out$levels <- 5 } if (is.null(out$leg$digits)) { dif <- diff(out$range) if (dif == 0) { out$leg_digits = 0; } else { out$leg$digits <- max(0, -floor(log10(dif/10))) } } if (is.null(out$leg$loc)) out$leg$loc <- "right" brks <- seq(out$range[1], out$range[2], length.out = length(out$cols)) grps <- cut(out$v, breaks = brks, include.lowest = TRUE) out$main_cols <- out$cols[grps] out } .vect.legend.interval <- function(out, dig.lab=3, ...) { nmx <- length(out$uv) if (!is.numeric(out$v)) { out$v <- as.integer(as.factor(out$v)) } if (is.null(out$breaks)) { out$breaks <- min(5, nmx) } if (length(out$breaks) == 1) { out$breaks <- .get_breaks(out$v, out$breaks, out$breakby, out$range) } fz <- cut(out$v, out$breaks, include.lowest=TRUE, right=FALSE, dig.lab=dig.lab) out$vcut <- as.integer(fz) levs <- levels(fz) nlevs <- length(levs) cols <- out$cols ncols <- length(cols) if (nlevs < ncols) { i <- trunc((ncols / nlevs) * 1:nlevs) cols <- cols[i] } else { cols <- rep_len(cols, nlevs) } out$cols <- cols out$leg$fill <- cols out$legend_type <- "classes" if (!is.null(out$leg$legend)) { if (length(out$leg$legend) != nlevs) { warn("plot", "legend does not match number of levels") out$leg$legend <- rep_len(out$leg$legend, nlevs) } } else { levs <- gsub("]", "", gsub(")", "", gsub("\\[", "", levs))) levs <- paste(levs, collapse=",") m <- matrix(as.numeric(unlist(strsplit(levs, ","))), ncol=2, byrow=TRUE) m <- apply(m, 1, function(i) paste(i, collapse=" - ")) out$leg$legend <- m } if (is.null(out$leg$x)) { # && is.null(out$leg$ext)) { out$leg$x <- "top" } out$main_cols <- out$cols[out$vcut] if (!is.null(out$colNA)) { out$main_cols[is.na(out$main_cols)] <- out$colNA } out } .plot.vect.map <- function(x, out, xlab="", ylab="", type = "n", yaxs="i", xaxs="i", asp=out$asp, density=NULL, angle=45, border="black", dig.lab=3, main="", sort=TRUE, ...) { if ((!out$add) & (!out$legend_only)) { if (!any(is.na(out$mar))) { graphics::par(mar=out$mar) } plot(out$lim[1:2], out$lim[3:4], type="n", xlab=xlab, ylab=ylab, asp=asp, xaxs=xaxs, yaxs=yaxs, axes=FALSE, main=main) if (!is.null(out$background)) { usr <- graphics::par("usr") graphics::rect(usr[1], usr[3], usr[2], usr[4], col=out$background) } } out$leg$density <- density out$leg$angle <- angle out$leg$border <- border out$legend_sort <- isTRUE(sort) nuq <- length(out$uv) if (out$legend_type == "none") { out <- .vect.legend.none(out) } else if (out$legend_type == "classes") { out <- .vect.legend.classes(out) } else if (out$legend_type == "interval") { if (nuq < 2) { out <- .vect.legend.classes(out, ...) } else { out <- .vect.legend.interval(out, dig.lab=dig.lab) } } else if (out$legend_type == "depends") { if (nuq < 11) { out <- .vect.legend.classes(out) } else if (!is.numeric(out$uv)) { #if (nuq < 21) out <- .vect.legend.classes(out) } else { out <- .vect.legend.interval(out, dig.lab=dig.lab) } } else { if (nuq == 1) { out <- .vect.legend.classes(out) } else { out <- .vect.legend.continuous(out) out$leg$density <- NULL } } if (!out$legend_only) { out <- .vplot(x, out, ...) } if (out$axes) { out <- .plot.axes(out) } if (out$legend_draw) { if (out$legend_type == "continuous") { out$legpars <- do.call(.plot.cont.legend, list(x=out)) } else { out$legpars <- do.call(.plot.class.legend, out$leg) } } out } .prep.vect.data <- function(x, y, type, cols=NULL, mar=NULL, legend=TRUE, legend.only=FALSE, levels=NULL, add=FALSE, range=NULL, breaks=NULL, breakby="eqint", xlim=NULL, ylim=NULL, colNA=NA, alpha=NULL, axes=TRUE, main=NULL, buffer=TRUE, background=NULL, pax=list(), plg=list(), ext=NULL, grid=FALSE, las=0, ...) { out <- list() out$ngeom <- nrow(x) e <- as.vector(ext(x)) out$ext <- e if (!is.null(ext)) { stopifnot(inherits(ext, "SpatExtent")) x <- crop(x, ext) out$ext <- as.vector(ext(x)) out$lim <- ext } else { if (!is.null(xlim)) { stopifnot(length(xlim) == 2) e[1:2] <- sort(xlim) } else if (buffer) { dx <- diff(e[1:2]) / 50 e[1:2] <- e[1:2] + c(-dx, dx) } if (!is.null(ylim)) { stopifnot(length(ylim) == 2) e[3:4] <- sort(ylim) } else if (buffer) { dy <- diff(e[3:4]) / 50 e[3:4] <- e[3:4] + c(-dy, dy) } out$lim <- e } out$add <- isTRUE(add) out$axes <- isTRUE(axes) out$axs <- as.list(pax) if (is.null(out$axs$las)) out$axs$las <- las out$draw_grid <- isTRUE(grid) out$leg <- as.list(plg) out$leg$geomtype <- geomtype(x) out$asp <- 1 out$lonlat <- is.lonlat(x, perhaps=TRUE, warn=FALSE) if (out$lonlat) { out$asp <- 1/cos((mean(out$ext[3:4]) * pi)/180) } out$breaks <- breaks out$breakby <- breakby out$background <- background v <- unlist(x[, y, drop=TRUE], use.names=FALSE) if (!is.null(range)) { range <- sort(range) v[v < range[1]] <- NA v[v > range[2]] <- NA if (all(is.na(v))) { v <- NULL y <- "" type = "none" } else { out$range <- range } out$range_set <- TRUE } else { if (!is.null(v)) { out$range <- range(v, na.rm=TRUE) } out$range_set <- FALSE } out$v <- v out$uv <- unique(out$v) if (missing(type)) { type <- "depends" } else { type <- match.arg(type, c("continuous", "classes", "interval", "depends", "none")) } out$levels <- levels if (type=="none") { legend <- FALSE legend_only <- FALSE } out$legend_type <- type if (is.null(cols)) { if (type == "none") { if (out$leg$geomtype %in% c("lines", "points")) { cols <- "black" } } else { cols <- rev(grDevices::rainbow(100, start=.1, end=0.9)) } } if (!is.null(alpha)) { alpha <- clamp(alpha[1]*255, 0, 255) cols <- grDevices::rgb(t(grDevices::col2rgb(cols)), alpha=alpha, maxColorValue=255) } else { alpha <- 255 } out$cols <- cols out$legend_draw <- isTRUE(legend) out$legend_only <- isTRUE(legend.only) if (is.null(mar)) { if (out$legend_draw) { mar=c(3.1, 3.1, 2.1, 7.1) } else { mar=c(3.1, 3.1, 2.1, 2.1) } } out$mar <- rep_len(mar, 4) out$skipNA <- TRUE if (!is.null(colNA)) { if (!is.na(colNA)) { out$colNA <- grDevices::rgb(t(grDevices::col2rgb(colNA)), alpha=alpha, maxColorValue=255) out$r[is.na(out$r)] <- out$colNA out$skipNA <- FALSE } else { out$colNA <- NULL } } .plot.vect.map(x, out, main=main, ...) } setMethod("plot", signature(x="SpatVector", y="character"), function(x, y, col=NULL, type, mar=NULL, legend=TRUE, add=FALSE, axes=!add, main=y, buffer=TRUE, background=NULL, grid=FALSE, ext=NULL, plg=list(), pax=list(), nr, nc, ...) { if (nrow(x) == 0) { error("plot", "SpatVector has zero geometries") } y <- trimws(y) if (any(is.na(match(y, c("", names(x)))))) { i <- is.na(match(y, names(x))) error("plot", paste(paste(y[i], collapse=",")), " is not a name in x") } nrnc <- c(1,1) if (length(y) > 1) { nrnc <- .get_nrnc(nr, nc, length(y)) old.par <- graphics::par(no.readonly =TRUE) on.exit(graphics::par(old.par)) graphics::par(mfrow=nrnc) } if (is.character(legend)) { plg$x <- legend legend <- TRUE } for (i in 1:length(y)) { if (length(y) > 1) { newrow <- (nrnc[2] == 1) | ((i %% nrnc[2]) == 1) lastrow <- i > (prod(nrnc) - nrnc[2]) if (lastrow) { if (newrow) { pax$sides <- 1:2 } else { pax$sides <- 1 } } else if (newrow) { pax$sides <- 2 } else { pax$sides <- 0 } } if (missing(col)) col <- NULL if (y[i] == "") { out <- .prep.vect.data(x, y="", type="none", cols=col, mar=mar, plg=list(), pax=pax, legend=FALSE, add=add, axes=axes, main=main[i], buffer=buffer, background=background, grid=grid, ext=ext, ...) } else { out <- .prep.vect.data(x, y[i], type=type, cols=col, mar=mar, plg=plg, pax=pax, legend=isTRUE(legend), add=add, axes=axes, main=main[i], buffer=buffer, background=background, grid=grid, ext=ext, ...) } } invisible(out) } ) setMethod("plot", signature(x="SpatVector", y="numeric"), function(x, y, ...) { y <- round(y) if (any(y > ncol(x))) { error("plot", paste("x only has", ncol(x), " columns")) } y[y<0] <- 0 y <- c("", names(x))[y+1] out <- plot(x, y, ...) invisible(out) } ) setMethod("plot", signature(x="SpatVector", y="missing"), function(x, y, ...) { out <- plot(x, "", ...) invisible(out) } ) setMethod("plot", signature(x="SpatVectorProxy", y="missing"), function(x, y, ...) { plot(ext(x), ...) } ) terra/R/write.R0000644000175000017500000001064714202622603013204 0ustar nileshnilesh # not exported if (!isGeneric("blockSize")) {setGeneric("blockSize", function(x, ...) standardGeneric("blockSize"))} setMethod("blockSize", signature(x="SpatRaster"), function(x, n) { opt <- spatOptions("", FALSE, ncopies=n) b <- x@ptr$getBlockSizeR(n, opt$memfrac) b$row <- b$row + 1 b } ) setMethod("writeStart", signature(x="SpatRaster", filename="character"), function(x, filename="", overwrite=FALSE, n=4, ...) { filename <- enc2utf8(filename) opt <- spatOptions(filename, overwrite, ncopies=n, ...) ok <- x@ptr$writeStart(opt) messages(x, "writeStart") b <- x@ptr$getBlockSizeWrite() b$row <- b$row + 1 b } ) setMethod("writeStop", signature(x="SpatRaster"), function(x) { success <- x@ptr$writeStop() messages(x, "writeStop") f <- sources(x) if (f != "") { x <- rast(f) } return(x) } ) setMethod("writeValues", signature(x="SpatRaster", v="vector"), function(x, v, start, nrows) { success <- x@ptr$writeValues(v, start-1, nrows) messages(x, "writeValues") invisible(success) } ) setMethod("writeRaster", signature(x="SpatRaster", filename="character"), function(x, filename="", overwrite=FALSE, ...) { filename <- trimws(filename) stopifnot(filename != "") if (tools::file_ext(filename) %in% c("nc", "cdf") || isTRUE(list(...)$filetype=="netCDF")) { warn("consider writeCDF to write ncdf files") } filename <- enc2utf8(filename) opt <- spatOptions(filename, overwrite, ...) x@ptr <- x@ptr$writeRaster(opt) x <- messages(x, "writeRaster") invisible(rast(filename)) } ) get_filetype <- function(filename) { ext <- tolower(tools::file_ext(filename)) if (ext == "shp" || ext == "") { "ESRI Shapefile" } else if (ext == "gpkg") { "GPKG" } else if (ext == "gml") { "GML" } else if (ext == "json") { "GeoJSON" } else if (ext == "cdf") { "netCDF" } else if (ext == "svg") { "SVG" } else if (ext == "kml") { "KML" } else if (ext == "vct") { "Idrisi" } else { error("writeVector", "cannot guess filetype from filename") } } setMethod("writeVector", signature(x="SpatVector", filename="character"), function(x, filename, filetype=NULL, layer=NULL, insert=FALSE, overwrite=FALSE, options="ENCODING=UTF-8") { filename <- trimws(filename) filename <- enc2utf8(filename) if (filename == "") { error("writeVector", "provide a filename") } if (is.null(filetype)) { filetype <- get_filetype(filename) } if (is.null(layer)) layer <- tools::file_path_sans_ext(basename(filename)) layer <- trimws(layer) if (is.null(options)) { options <- ""[0] } if (filetype == "ESRI Shapefile") { nms <- names(x) i <- nchar(nms) > 10 if (any(i)) { nms[i] <- substr(nms[i], 1, 10) testnms <- make.unique(nms, sep="") if (!all(testnms == nms)) { i <- which(i) newnms <- substr(nms[i], 1, 9) newnms <- make.unique(newnms, sep="") j <- which(nchar(newnms) == 9) newnms[j] <- paste0(newnms[j], "0") nms[i] <- newnms } x@ptr <- x@ptr$deepcopy() names(x) <- nms } } success <- x@ptr$write(filename, layer, filetype, insert[1], overwrite[1], options) messages(x, "writeVector") invisible(TRUE) } ) # setMethod("writeVector", signature(x="SpatVectorProxy", filename="character"), # function(x, filename, filetype=NULL, layer=NULL, insert=FALSE, overwrite=FALSE, options="ENCODING=UTF-8") { # filename <- trimws(filename) # filename <- enc2utf8(filename) # if (filename == "") { # error("writeVector", "provide a filename") # } # if (is.null(filetype)) { # filetype <- get_filetype(filename) # } # if (is.null(layer)) layer <- tools::file_path_sans_ext(basename(filename)) # layer <- trimws(layer) # if (is.null(options)) { options <- ""[0] } # if (filetype == "ESRI Shapefile") { # nms <- names(x) # i <- nchar(nms) > 10 # if (any(i)) { # nms[i] <- substr(nms[i], 1, 10) # testnms <- make.unique(nms, sep="") # if (!all(testnms == nms)) { # i <- which(i) # newnms <- substr(nms[i], 1, 9) # newnms <- make.unique(newnms, sep="") # j <- which(nchar(newnms) == 9) # newnms[j] <- paste0(newnms[j], "0") # nms[i] <- newnms # } # x@ptr <- x@ptr$deepcopy() # names(x) <- nms # } # } # success <- x@ptr$write_proxy(filename, layer, filetype, insert[1], FALSE, overwrite[1], options) # messages(x, "writeVector") # invisible(TRUE) # } # ) terra/R/crosstab.R0000644000175000017500000000340514202043725013666 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : March 2009 # Version 1.0 # License GPL v3 # revised April 2011 # adapted November 2020 setMethod("crosstab", signature(x="SpatRaster", y="missing"), function(x, digits=0, long=FALSE, useNA=FALSE) { nl <- nlyr(x) if (nl < 2) { error("crosstab", "needs at least 2 layers") } nms <- names(x) opt <- terra:::spatOptions() b <- blockSize(x, 4) readStart(x) on.exit(readStop(x)) res <- NULL nc <- ncol(x) for (i in 1:b$n) { d <- readValues(x, b$row[i], b$nrows[i], 1, nc, TRUE) d <- lapply(1:nl, function(i) round(d[, i], digits=digits)) d <- do.call(table, c(d, useNA="ifany")) d <- as.data.frame(d) res <- rbind(res, d) } res <- res[res$Freq > 0, ,drop=FALSE] # some complexity to aggregate keeping # variables that are NA if (useNA) { for (i in 1:(ncol(res)-1)) { if (any(is.na(res[,i]))) { res[,i] <- factor(res[,i], levels=c(levels(res[,i]), NA), exclude=NULL) } } } res <- aggregate(res[, ncol(res), drop=FALSE], res[, 1:(ncol(res)-1), drop=FALSE], sum) for (i in 1:(ncol(res)-1)) { # get rid of factors res[,i] <- as.numeric(as.character(res[,i])) } if (nrow(res) == 0) { res <- data.frame(matrix(nrow=0, ncol=length(nms)+1)) } nms <- make.names(nms, unique=TRUE) colnames(res) <- c(nms, "Freq") if (! useNA ) { i <- apply(res, 1, function(x) any(is.na(x))) res <- res[!i, ,drop=FALSE] } if (!long) { f <- eval(parse(text=paste("Freq ~ ", paste(nms , collapse="+")))) res <- stats::xtabs(f, data=res, addNA=useNA) } else { res <- res[res$Freq > 0, ,drop=FALSE] res <- res[order(res[,1], res[,2]), ] rownames(res) <- NULL } return(res) } ) terra/R/Aclasses.R0000644000175000017500000000433714201035747013615 0ustar nileshnilesh# Author: Robert J. Hijmans, r.hijmans@gmail.com # Date : November 2017 # Version 0 # License GPL v3 setClass("SpatRaster", representation ( ptr = "C++Object" ), prototype ( ptr = NULL ), validity = function(object) { if (is.null(object@ptr) || is(object@ptr, "Rcpp_SpatRaster")){ return(TRUE) } else { return(FALSE) } } ) setClass("SpatRasterDataset", representation ( ptr = "C++Object" ), prototype ( ptr = NULL ), validity = function(object) { if (is.null(object@ptr) || is(object@ptr, "Rcpp_SpatRasterStack")){ return(TRUE) } else { return(FALSE) } } ) setClass("SpatRasterCollection", representation ( ptr = "C++Object" ), prototype ( ptr = NULL ), validity = function(object) { if (is.null(object@ptr) || is(object@ptr, "Rcpp_SpatRasterCollection")){ return(TRUE) } else { return(FALSE) } } ) setClass("SpatVector", representation ( ptr = "C++Object" ), prototype ( ptr = NULL ), validity = function(object) { if (is.null(object@ptr) || is(object@ptr, "Rcpp_SpatVector")){ return(TRUE) } else { return(FALSE) } } ) setClass("SpatVectorProxy", representation ( ptr = "C++Object" ), prototype ( ptr = NULL ), validity = function(object) { if (is.null(object@ptr) || is(object@ptr, "Rcpp_SpatVectorProxy")){ return(TRUE) } else { return(FALSE) } } ) setClass("SpatVectorCollection", representation ( ptr = "C++Object" ), prototype ( ptr = NULL ), validity = function(object) { if (is.null(object@ptr) || is(object@ptr, "Rcpp_SpatVectorCollection")){ return(TRUE) } else { return(FALSE) } } ) setClass("SpatExtent", representation ( ptr = "C++Object" ), prototype ( ptr = NULL ), validity = function(object) { if (is.null(object@ptr) || is(object@ptr, "Rcpp_SpatExtent")){ return(TRUE) } else { return(FALSE) } } ) setClass("SpatOptions", representation ( ptr = "C++Object" ), prototype ( ptr = NULL ), validity = function(object) { if (is.null(object@ptr) || is(object@ptr, "Rcpp_SpatOptions")){ return(TRUE) } else { return(FALSE) } } ) terra/R/names.R0000644000175000017500000001073214201035747013156 0ustar nileshnilesh# Author: Robert J. Hijmans # Date: October 2018 # Version 1.0 # License GPL v3 setMethod("names", signature(x="SpatRaster"), function(x) { nms <- x@ptr$names Encoding(nms) <- "UTF-8" nms } ) setMethod("names<-", signature(x="SpatRaster"), function(x, value) { value <- enc2utf8(as.character(value)) if (length(value) != nlyr(x)) { error("names<-", "incorrect number of names") } x@ptr <- x@ptr$deepcopy() if (! x@ptr$setNames(value, FALSE)) { error("names<-", "cannot set these names") } return(x) } ) .raster_names_check <- function(x, value, index, validate) { value <- enc2utf8(as.character(value)) if (!all(index == 1:nlyr(x))) { n <- names(x) n[index] <- value value <- n } if (length(value) != nlyr(x)) { error("names<-", "incorrect number of names") } if (validate) { value <- make.names(value, unique = TRUE) } value } .vector_names_check <- function(x, value, index, validate) { value <- enc2utf8(as.character(value)) if (!all(index == 1:ncol(x))) { n <- names(x) n[index] <- value value <- n } if (length(value) != ncol(x)) { error("names<-", "incorrect number of names") } if (validate) { value <- make.names(value, unique = TRUE) } value } setMethod("set.names", signature(x="SpatRaster"), function(x, value, index=1:nlyr(x), validate=FALSE) { value <- .raster_names_check(x, value, index, validate) if (! x@ptr$setNames(value, FALSE)) { error("set.names", "cannot set these names") } invisible(TRUE) } ) setMethod("names", signature(x="SpatRasterDataset"), function(x) { nms <- x@ptr$names Encoding(nms) <- "UTF-8" nms } ) setMethod("names<-", signature(x="SpatRasterDataset"), function(x, value) { x@ptr <- x@ptr$deepcopy() x@ptr$names <- enc2utf8(as.character(value)) x } ) setMethod("set.names", signature(x="SpatRasterDataset"), function(x, value, index=1:length(x), validate=FALSE) { value <- .raster_names_check(x, value, index, validate) x@ptr$names <- value invisible(TRUE) } ) setMethod("varnames", signature(x="SpatRasterDataset"), function(x) { nms <- x@ptr$names Encoding(nms) <- "UTF-8" nms } ) setMethod("varnames<-", signature(x="SpatRasterDataset"), function(x, value) { value <- enc2utf8(as.character(value)) x@ptr <- x@ptr$deepcopy() x@ptr$names <- value x } ) setMethod("names", signature(x="SpatVector"), function(x) { nms <- x@ptr$names Encoding(nms) <- "UTF-8" nms } ) setMethod("names", signature(x="SpatVectorProxy"), function(x) { nms <- x@ptr$v$names Encoding(nms) <- "UTF-8" nms } ) setMethod("names<-", signature(x="SpatVector"), function(x, value) { if (length(value) != ncol(x)) { error("names<-,SpatVector", "incorrect number of names") } value <- enc2utf8(as.character(value)) x@ptr <- x@ptr$deepcopy() x@ptr$names <- value if (any(names(x) != value)) { warn("names<-", "some names were changed to make them valid and/or unique") } return(x) } ) setMethod("set.names", signature(x="SpatVector"), function(x, value, index=1:ncol(x), validate=FALSE) { value <- .vector_names_check(x, value, index, validate) x@ptr$names <- value invisible(TRUE) } ) setMethod("varnames", signature(x="SpatRaster"), function(x) { nms <- x@ptr$get_sourcenames() Encoding(nms) <- "UTF-8" nms } ) setMethod("varnames<-", signature(x="SpatRaster"), function(x, value) { value <- enc2utf8(as.character(value)) x@ptr <- x@ptr$deepcopy() if (!x@ptr$set_sourcenames(value)) { error("varnames<-,SpatRaster", "cannot set these names") } return(x) } ) setMethod("longnames", signature(x="SpatRasterDataset"), function(x) { nms <- x@ptr$long_names Encoding(nms) <- "UTF-8" nms } ) setMethod("longnames", signature(x="SpatRaster"), function(x) { nms <- x@ptr$get_sourcenames_long() Encoding(nms) <- "UTF-8" nms } ) setMethod("longnames<-", signature(x="SpatRasterDataset"), function(x, value) { x@ptr <- x@ptr$deepcopy() x@ptr$long_names <- enc2utf8(as.character(value)) return(x) } ) setMethod("longnames<-", signature(x="SpatRaster"), function(x, value) { x@ptr <- x@ptr$deepcopy() value <- enc2utf8(as.character(value)) if (!x@ptr$set_sourcenames_long(value)) { error("longnames<-,SpatRaster", "cannot set these names") } return(x) } ) terra/R/rapp.R0000644000175000017500000000432614201035747013017 0ustar nileshnilesh setMethod("rapp", signature(x="SpatRaster"), function(x, first, last, fun, ..., allyrs=FALSE, fill=NA, clamp=FALSE, filename="", overwrite=FALSE, wopt=list()) { stopifnot(hasValues(x)) firstval <- lastval <- NA if (inherits(first, "SpatRaster")) { first <- first[[1]] stopifnot(hasValues(first)) } else { if (!is.numeric(first)) { error("rapp", "argument `first` should be numeric or SpatRaster") } firstval <- first stopifnot(first %in% 1:nlyr(x)) } if (inherits(last, "SpatRaster")) { last <- last[[1]] stopifnot(hasValues(last)) } else { if (!is.numeric(last)) { error("rapp", "argument `last` should be numeric or SpatRaster") } lastval <- last stopifnot(last %in% 1:nlyr(x)) } if (!(is.na(firstval)) && (!(is.na(lastval)))) { error("rapp", "argument `first` or `last` must be a SpatRaster. Or use `app`") } if (!is.na(firstval)) { index <- last; } else if (!is.na(lastval)) { index <- first } else { index <- c(first, last) } compareGeom(x, index, lyrs=FALSE, crs=FALSE, warncrs=FALSE, ext=TRUE, rowcol=TRUE, res=FALSE) if (!allyrs) { txtfun <- .makeTextFun(match.fun(fun)) if (inherits(txtfun, "character")) { if (txtfun %in% .cpp_funs) { opt <- spatOptions(filename, overwrite, wopt=wopt) na.rm <- isTRUE(list(...)$na.rm) x@ptr <- x@ptr$rapply(index@ptr, firstval, lastval, txtfun, clamp, na.rm, opt) return(messages(x, "rapp")) } } } out <- rast(x) v <- x@ptr$rappvals(index@ptr, firstval, lastval, clamp, allyrs, fill, 0, 1) v <- sapply(v, fun, ...) if (is.list(v)) { error("rapp", "values returned by 'fun' do not have the same length for each cell") } nc <- ncol(out) trans = FALSE if (NCOL(v) == nc) { trans = TRUE nlyr(out) <- nrow(v) } else if (NROW(v) == nc) { nlyr(out) <- NCOL(v) } else if (length(v) == nc) { nlyr(out) <- 1 } b <- writeStart(out, filename, overwrite, wopt=wopt, n=nlyr(x)*3) for (i in 1:b$n) { v <- x@ptr$rappvals(index@ptr, firstval, lastval, clamp, allyrs, fill, b$row[i]-1, b$nrows[i]) v <- sapply(v, fun, ...) if (trans) v = t(v) writeValues(out, as.vector(v), b$row[i], b$nrows[i]) } out <- writeStop(out) return(out) } ) terra/R/polygons.R0000644000175000017500000000000014201035747013710 0ustar nileshnileshterra/R/draw.R0000644000175000017500000000451114201035747013006 0ustar nileshnilesh RS_locator <- function(n, type, id=FALSE, pch=20, ...) { # locator that also works in RStudio # Berry Boessenkool # https://stackoverflow.com/a/65147220/635245 on.exit(return(cbind(x, y))) x <- y <- NULL for (i in seq_len(n)) { p <- graphics::locator(1) if (is.null(p)) break # ESC x <- c(x, p$x) y <- c(y, p$y) points(x, y, type=type, pch=pch, ...) if (id) { text(p$x, p$y, labels=i, pos=4, ...) } } } .drawPol <- function(n=1000, id=FALSE, ...) { #xy <- graphics::locator(n=1000, type="l", col=col, lwd=lwd, ...) #xy <- cbind(xy$x, xy$y) xy <- RS_locator(n, "l", id=id, ...) xy <- rbind(xy, xy[1,]) graphics::lines(xy[(length(xy[,1])-1):length(xy[,1]),], ...) g <- cbind(1,1,xy,0) vect(g, "polygons") } .drawLin <- function(n=1000, ...) { #xy <- graphics::locator(n=1000, type="l", col=col, lwd=lwd, ...) #xy <- cbind(xy$x, xy$y) xy <- RS_locator(n, "l", ...) g <- cbind(1,1,xy) vect(g, "lines") } .drawPts <- function(n=1000, ...) { #xy <- graphics::locator(n=1000, type="p", col=col, lwd=lwd, ...) #xy <- cbind(xy$x, xy$y) xy <- RS_locator(n, "p", ...) g <- cbind(1:nrow(xy), 1, xy) vect(g, "points") } .drawExt <- function(...) { loc1 <- graphics::locator(n=1, type="p", pch="+", ...) loc2 <- graphics::locator(n=1, type="p", pch="+", ...) loc <- rbind(unlist(loc1), unlist(loc2)) e <- c(min(loc[,'x']), max(loc[,'x']), min(loc[,'y']), max(loc[,'y'])) if (e[1] == e[2]) { e[1] <- e[1] - 0.0000001 e[2] <- e[2] + 0.0000001 } if (e[3] == e[4]) { e[3] <- e[3] - 0.0000001 e[4] <- e[4] + 0.0000001 } p <- rbind(c(e[1], e[3]), c(e[1], e[4]), c(e[2], e[4]), c(e[2], e[3]), c(e[1], e[3]) ) graphics::lines(p, ...) return(ext(e)) } setMethod("draw", signature(x="character"), function(x="extent", col="red", lwd=2, id=FALSE, n=1000, ...){ x <- match.arg(tolower(x), c("extent", "polygon", "lines", "points")) if (x == "extent") { .drawExt(col=col, lwd=lwd, ...) } else if (x == "polygon") { .drawPol(n, col=col, lwd=lwd, id=id, ...) } else if (x == "lines") { .drawLin(n, col=col, lwd=lwd, id=id, ...) } else if (x == "points" || x == "multipoints" ) { .drawPts(n, col=col, id=id, ...) } } ) setMethod("draw", signature(x="missing"), function(x="extent", ...){ draw("extent", ...) } ) terra/R/Arith_generics.R0000644000175000017500000003164514201035747015007 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : September 2018 # Version 1.0 # License GPL v3 setMethod("Arith", signature(e1="SpatExtent", e2="numeric"), function(e1, e2){ oper <- as.vector(.Generic)[1] if (oper == "%%") { e1@ptr <- e1@ptr$align(e2[1], "") } else if (oper == "+") { e2 <- rep_len(e2, 4) e2[c(1,3)] <- -e2[c(1,3)] e1 <- ext(as.vector(e1) + e2) } else if (oper == "-") { e2 <- rep_len(e2, 4) e2[c(1,3)] <- -e2[c(1,3)] e1 <- ext(as.vector(e1) - e2) } else if (oper == "*") { e2 <- abs(rep_len(e2, 4)) e1 <- as.vector(e1) dx <- (e1[2] - e1[1]) dy <- (e1[4] - e1[3]) mx <- e1[1] + dx/2 my <- e1[3] + dy/2 e1[1] <- mx - (dx/2)*e2[1] e1[2] <- mx + (dx/2)*e2[2] e1[3] <- my - (dy/2)*e2[3] e1[4] <- my + (dy/2)*e2[4] e1 <- ext(e1) } else if (oper == "/") { e2 <- abs(rep_len(e2, 4)) e1 <- as.vector(e1) dx <- (e1[2] - e1[1]) dy <- (e1[4] - e1[3]) mx <- e1[1] + dx/2 my <- e1[3] + dy/2 e1[1] <- mx - dx/(2*e2[1]) e1[2] <- mx + dx/(2*e2[2]) e1[3] <- my - dy/(2*e2[3]) e1[4] <- my + dy/(2*e2[4]) e1 <- ext(e1) } else { error(oper, "only +, -, *, / and %% are supported") } if (!e1@ptr$valid) { error(oper, "this would create an invalid extent") } e1 } ) setMethod("Arith", signature(e1="numeric", e2="SpatExtent"), function(e1, e2) { oper <- as.vector(.Generic)[1] if (oper == "%%") { error("%%", "only 'Spatextent %% numeric' (in that order) is supported") } else if (oper == "+") { return(e2 + e1) } else if (oper == "-") { error("-", "only 'Spatextent - numeric' (in that order) is supported") } else if (oper == "*") { return(e2 * e1) } else if (oper == "/") { error("/", "only 'Spatextent / numeric' (in that order) is supported") } else { error(oper, "only +, -, *, / and %% are supported") } if (!e1@ptr$valid) { error(oper, "this would create an invalid extent") } e1 } ) setMethod("Arith", signature(e1="SpatExtent", e2="SpatExtent"), function(e1, e2){ oper <- as.vector(.Generic)[1] if (oper == "+") { e1@ptr <- e1@ptr$deepcopy() e1@ptr$union(e2@ptr) } else if (oper == "*") { e1@ptr <- e1@ptr$intersect(e2@ptr) } else if (oper == "/") { d <- c(diff(e1[1:2]) / diff(e2[1:2]), diff(e1[3:4]) / diff(e2[3:4])) names(d) <- c("x", "y") return(d) } else { error(oper, "only +, *, and / are supported for SpatExtent") } if (!e1@ptr$valid) { error(oper, "this would create an invalid extent") } e1 } ) setMethod("Arith", signature(e1="SpatVector", e2="SpatVector"), function(e1, e2){ oper <- as.vector(.Generic)[1] if (oper == "+") { e1@ptr <- e1@ptr$union(e2@ptr) } else if (oper == "*") { e1@ptr <- e1@ptr$intersect(e2@ptr) } else if (oper == "-") { e1@ptr <- e1@ptr$erase(e2@ptr) } else { error(oper, "only operators +, *, and - are supported for SpatVector") } messages(e1, oper) } ) setMethod("Arith", signature(e1="SpatRaster", e2="SpatRaster"), function(e1, e2){ opt <- spatOptions() oper <- as.vector(.Generic)[1] stopifnot(oper %in% c("+", "-", "^", "*", "/", "%%")) oper <- ifelse(oper == "%%", "%", oper) e1@ptr <- e1@ptr$arith_rast(e2@ptr, oper, opt) messages(e1, oper) } ) setMethod("Arith", signature(e1="SpatRaster", e2="numeric"), function(e1, e2){ oper <- as.vector(.Generic)[1] stopifnot(oper %in% c("+", "-", "^", "*", "/", "%%")) opt <- spatOptions() oper <- ifelse(oper == "%%", "%", oper) e1@ptr <- e1@ptr$arith_numb(e2, oper, FALSE, opt) messages(e1, oper) } ) setMethod("Arith", signature(e1="SpatRaster", e2="missing"), function(e1, e2){ methods::callGeneric(0, e1) } ) setMethod("Arith", signature(e1="numeric", e2="SpatRaster"), function(e1, e2){ oper <- as.vector(.Generic)[1] stopifnot(oper %in% c("+", "-", "^", "*", "/", "%%")) opt <- spatOptions() oper <- ifelse(oper == "%%", "%", oper) e2@ptr <- e2@ptr$arith_numb(e1, oper, TRUE, opt) messages(e2, oper) } ) setMethod("Compare", signature(e1="SpatRaster", e2="SpatRaster"), function(e1, e2){ opt <- spatOptions() oper <- as.vector(.Generic)[1] e1@ptr <- e1@ptr$arith_rast(e2@ptr, oper, opt) messages(e1, oper) } ) setMethod("Compare", signature(e1="SpatRaster", e2="numeric"), function(e1, e2){ oper <- as.vector(.Generic)[1] opt <- spatOptions() e1@ptr <- e1@ptr$arith_numb(e2, oper, FALSE, opt) messages(e1, oper) } ) setMethod("Compare", signature(e1="numeric", e2="SpatRaster"), function(e1, e2){ oper <- as.vector(.Generic)[1] opt <- spatOptions() e2@ptr <- e2@ptr$arith_numb(e1, oper, TRUE, opt) messages(e2, oper) } ) getFactTable <- function(x, table, sender="%in%") { if (!is.factor(x)) { error(sender, "Can only match character values if x is categorical") } if (nlyr(x) != 1) { error(sender, "matching with character values is only supported for single layer SpatRaster") } d <- cats(x)[[1]] levs <- levels(x)[[1]] m <- na.omit(match(table, levs)) if (length(m) == 0) { return(as.logical(x*0)) } d[m,1] } setMethod("Compare", signature(e1="SpatRaster", e2="character"), function(e1, e2){ oper <- as.vector(.Generic)[1] e2 <- getCatIDs(e1, e2, "==") if (oper != "==") { error(oper, "only '==' is supported with categorical comparisons") } if (length(e2) == 0) { return(as.logical(e1*0)) } if (length(e2) != 1) { error(oper, "comparisons only supported for single values (see %in% and match)") } opt <- spatOptions() e1@ptr <- e1@ptr$arith_numb(e2, oper, TRUE, opt) messages(e1, oper) } ) setMethod("Logic", signature(e1="SpatRaster", e2="SpatRaster"), function(e1, e2){ oper <- as.vector(.Generic)[1] opt <- spatOptions() e1@ptr <- e1@ptr$logic_rast(e2@ptr, oper, opt) messages(e1, oper) } ) setMethod("Logic", signature(e1="SpatRaster", e2="numeric"), function(e1, e2){ opt <- spatOptions() oper <- as.vector(.Generic)[1] e2 <- as.logical(e2) e1@ptr <- e1@ptr$logic_numb(e2, oper, opt) messages(e1, oper) } ) setMethod("Logic", signature(e1="numeric", e2="SpatRaster"), function(e1, e2){ opt <- spatOptions() oper <- as.vector(.Generic)[1] e1 <- as.logical(e1) e2@ptr <- e2@ptr$logic_numb(e1, oper, opt) messages(e2, oper) } ) setMethod("Logic", signature(e1="SpatRaster", e2="logical"), function(e1, e2){ opt <- spatOptions() oper <- as.vector(.Generic)[1] e1@ptr <- e1@ptr$logic_numb(e2, oper, opt) messages(e1, oper) } ) setMethod("Logic", signature(e1="logical", e2="SpatRaster"), function(e1, e2){ opt <- spatOptions() oper <- as.vector(.Generic)[1] e2@ptr <- e2@ptr$logic_numb(e1, oper, opt) messages(e2, oper) } ) setMethod("!", signature(x="SpatRaster"), function(x) { x == 0 } ) setMethod("isTRUE", signature(x="SpatRaster"), function(x) { opt <- spatOptions() x@ptr <- x@ptr$is_true(opt) messages(x, "isTRUE") } ) setMethod("isFALSE", signature(x="SpatRaster"), function(x) { opt <- spatOptions() x@ptr <- x@ptr$is_false(opt) messages(x, "isFALSE") } ) setMethod("as.logical", signature(x="SpatRaster"), function(x) { isTRUE(x) } ) setMethod("is.bool", signature(x="SpatRaster"), function(x) { x@ptr$valueType == 3 } ) setMethod("is.int", signature(x="SpatRaster"), function(x) { x@ptr$valueType == 1 } ) setMethod("as.bool", signature(x="SpatRaster"), function(x, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$is_true(opt) messages(x, "as.boolean") } ) setMethod("as.int", signature(x="SpatRaster"), function(x, filename="", ...) { opt <- spatOptions(filename, ...) x@ptr <- x@ptr$math("trunc", opt) messages(x, "as.int") } ) setMethod("as.integer", signature(x="SpatRaster"), function(x, filename="", ...) { as.int(x, filename, x) } ) setMethod("is.na", signature(x="SpatRaster"), function(x) { opt <- spatOptions() x@ptr <- x@ptr$isnan(opt) messages(x, "is.na") } ) setMethod("is.nan", signature(x="SpatRaster"), function(x) { opt <- spatOptions() x@ptr <- x@ptr$isnan(opt) messages(x, "is.nan") } ) setMethod("is.finite", signature(x="SpatRaster"), function(x) { opt <- spatOptions() x@ptr <- x@ptr$isfinite(opt) messages(x, "is.finite") } ) setMethod("is.infinite", signature(x="SpatRaster"), function(x) { opt <- spatOptions() x@ptr <- x@ptr$isinfinite(opt) messages(x, "is.infinite") } ) .summarize <- function(x, ..., fun, na.rm=FALSE, filename="", overwrite=FALSE, wopt=list()) { dots <- list(...) add <- NULL cls <- FALSE if (length(dots) > 0) { cls <- sapply(dots, function(i) inherits(i, "SpatRaster")) if (!all(cls)) { add <- dots[!cls] if (!is.null(names(add))) { error(fun, "additional arguments cannot be names (except for `filename`, `overwrite` and `wopt`)") } i <- sapply(add, function(x) class(x) %in% c("logical", "integer", "numeric")) add <- unlist(add[i], use.names = FALSE) if (any(!i)) { error(fun, "invalid argument(s)") } } } if (any(cls)) { x <- sds(c(list(x), dots[cls])) } opt <- spatOptions(filename, overwrite, wopt=wopt) r <- rast() if (is.null(add)) { r@ptr <- x@ptr$summary(fun, na.rm, opt) } else { r@ptr <- x@ptr$summary_numb(fun, add, na.rm, opt) } messages(r, fun) r } setMethod("which.max", "SpatRaster", function(x) { opt <- spatOptions() x@ptr <- x@ptr$summary("which.max", TRUE, opt) messages(x, "which.max") } ) setMethod("which.min", "SpatRaster", function(x) { opt <- spatOptions() x@ptr <- x@ptr$summary("which.min", TRUE, opt) messages(x, "which.min") } ) setMethod("which.lyr", "SpatRaster", function(x) { opt <- spatOptions() x@ptr <- x@ptr$summary("which", TRUE, opt) messages(x, "which.lyr") } ) setMethod("Summary", signature(x="SpatRaster"), function(x, ..., na.rm=FALSE){ fun <- as.character(sys.call()[[1L]]) .summarize(x, ..., fun=fun, na.rm=na.rm) } ) setMethod("Summary", signature(x="SpatVector"), function(x, ..., na.rm=FALSE){ apply(values(x), 2, sys.call()[[1L]], ...) } ) setMethod("Summary", signature(x="SpatExtent"), function(x, ..., na.rm=FALSE){ e <- as.vector(x) x <- e[1:2] y <- e[3:4] fun <- as.character(sys.call()[[1L]]) if (fun == "range") { r <- c(diff(x), diff(y)) names(r) <- c("x", "y") r } else { c(callGeneric(x), callGeneric(y)) } } ) setMethod("mean", signature(x="SpatExtent"), function(x, ..., trim=NA, na.rm=FALSE){ if (!is.na(trim)) { warn("mean", "argument 'trim' is ignored") } e <- as.vector(x) c(mean(e[1:2]), mean(e[3:4])) } ) setMethod("mean", signature(x="SpatRaster"), function(x, ..., trim=NA, na.rm=FALSE){ if (!is.na(trim)) { warn("mean", "argument 'trim' is ignored") } .summarize(x, ..., fun="mean", na.rm=na.rm) } ) setMethod("mean", signature(x="SpatVector"), function(x, ..., trim=NA, na.rm=FALSE){ if (!is.na(trim)) { warn("mean", "argument 'trim' is ignored") } if (!is.null(list(...))) { warn("mean", "additional arguments are ignored") } colMeans(values(x)) } ) setMethod("median", signature(x="SpatRaster"), function(x, na.rm=FALSE, ...){ if (!is.logical(na.rm)) { error("median", "na.rm (the second argument) must be a logical value") } .summarize(x, ..., fun="median", na.rm=na.rm) } ) setMethod("median", signature(x="SpatVector"), function(x, na.rm=FALSE){ apply(values(x), 2, median, na.rm=na.rm) } ) setMethod("Compare", signature(e1="SpatExtent", e2="SpatExtent"), function(e1, e2){ oper <- as.vector(.Generic)[1] if (!(oper %in% c("==", "!=", ">", "<", ">=", "<="))) { error(oper, "is not implemented for SpatExtent") } return( e1@ptr$compare(e2@ptr, oper, 0.000001) ) } ) setMethod("stdev", signature(x="SpatRaster"), function(x, ..., pop=TRUE, na.rm=FALSE){ if (pop) { .summarize(x, ..., fun="std", na.rm=na.rm) } else { .summarize(x, ..., fun="sd", na.rm=na.rm) } } ) setMethod("modal", signature("SpatRaster"), function(x, ..., ties="first", na.rm=FALSE, filename="", overwrite=FALSE, wopt=list()) { opt <- spatOptions(filename, overwrite, wopt=wopt) dots <- list(...) add <- NULL if (length(dots) > 0) { cls <- sapply(dots, function(i) inherits(i, "SpatRaster")) if (any(cls)) { y <- c(dots[cls], x) x <- do.call(c, y) } if (!all(cls)) { dots <- dots[!cls] i <- sapply(dots, function(x) class(x) %in% c("logical", "integer", "numeric")) add <- unlist(dots[i], use.names = FALSE) } } if (is.null(add)) { add <- c(.5)[0] } x@ptr <- x@ptr$modal(add, ties[1], na.rm[1], opt) messages(x, "modal") } ) terra/R/merge.R0000644000175000017500000000303614201035747013151 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : June 2019 # Version 1.0 # License GPL v3 setMethod("merge", signature(x="SpatVector", y="data.frame"), function(x, y, ...) { v <- values(x) v$unique_nique_ique_que_e <- 1:nrow(v) m <- merge(v, y, ...) m <- m[order(m$unique_nique_ique_que_e), ] x <- x[na.omit(m$unique_nique_ique_que_e), ] m$unique_nique_ique_que_e <- NULL if (nrow(m) > nrow(x)) { error("merge", "using 'all.y=TRUE' is not allowed. Should it be?") } values(x) <- m x } ) setMethod("merge", signature(x="SpatRaster", y="SpatRaster"), function(x, y, ..., filename="", overwrite=FALSE, wopt=list()) { rc <- sprc(x, y, ...) opt <- spatOptions(filename, overwrite, wopt=wopt) x@ptr <- rc@ptr$merge(opt) messages(x, "merge") } ) setMethod("merge", signature(x="SpatRasterCollection", "missing"), function(x, filename="", ...) { opt <- spatOptions(filename, ...) out <- rast() out@ptr <- x@ptr$merge(opt) messages(out, "merge") } ) setMethod("mosaic", signature(x="SpatRaster", y="SpatRaster"), function(x, y, ..., fun="mean", filename="", overwrite=FALSE, wopt=list()) { rc <- sprc(x, y, ...) opt <- spatOptions(filename, overwrite, wopt=wopt) x@ptr <- rc@ptr$mosaic(fun, opt) messages(x, "mosaic") } ) setMethod("mosaic", signature(x="SpatRasterCollection", "missing"), function(x, fun="mean", filename="", ...) { opt <- spatOptions(filename, ...) out <- rast() out@ptr <- x@ptr$mosaic(fun, opt) messages(out, "mosaic") } ) terra/R/mergeTime.R0000644000175000017500000000516414201035747013774 0ustar nileshnilesh if (!isGeneric("fillTime")) {setGeneric("fillTime", function(x, ...) standardGeneric("fillTime"))} setMethod("fillTime", signature(x="SpatRaster"), function(x, filename="", ...) { tm <- time(x) if (any(is.na(tm))) { terra:::error("fillTime", "NA in time values") } if (any(table(tm)>1)) { terra:::error("fillTime", "duplicate time values") } if (is.unsorted(tm)) { warn("mergeTimelines", "sorting layers") ord <- order(tm) x <- x[[ ord ]] tm <- tm[ord] } d <- data.frame(time=seq(min(tm), max(tm), min(diff(tm)))) d <- merge(d, data.frame(time=tm, tm=tm), by=1, all.x=TRUE) b <- (!is.na(d[,2])) + 0 b <- cumsum(b) * b if (any(b==0)) { mx <- max(b) b[b==0] <- mx+1 r <- init(rast(x, nlyr=1), NA) x <- c(x, r) x <- x[[b]] } time(x) <- d[,1] if (filename != "") { writeRaster(x, ...) } else { x } } ) if (!isGeneric("mergeTime")) {setGeneric("mergeTime", function(x, ...) standardGeneric("mergeTime"))} setMethod("mergeTime", signature(x="SpatRasterDataset"), function(x, fun="mean", filename="", ...) { tim <- lapply(1:length(x), function(i) time(x[i])) if (any(sapply(tim, function(i) any(is.na(i))))) { terra:::error("mergeTime", "NA in time values") } if (any(sapply(tim, function(i) any(table(i)>1)))) { terra:::error("mergeTime", "duplicate time values") } us <- sapply(tim, is.unsorted) if (any(us)) { warn("mergeTime", paste("sorting layers of SpatRaster:", paste(us, collapse=", "))) us <- which(us) for (i in us) { ord <- order(tim[[i]]) x[i] <- x[i][[ ord ]] tim[[i]] <- tim[[i]][ord] } } z <- data.frame(time=sort(unique(do.call(c, tim)))) for (i in 1:length(tim)) { d <- data.frame(tim[[i]],tim[[i]]) names(d) <- c("time", paste0("x", i)) z <- merge(z, d, by=1, all.x=TRUE) } b <- (!is.na(z)) + 0 y <- apply(b, 1, function(i) paste(i, collapse="")) r <- rep(1, length(y)) for (i in 2:length(y)) { if (y[i] == y[i-1]) { r[i] <- r[i-1] } else { r[i] <- r[i-1] + 1 } } u <- unique(r) out <- list() d <- apply(b, 2, cumsum) * b for (i in u) { zz <- z[r==i, ,drop=FALSE] dd <- d[r==i, -1, drop=FALSE] tim <- zz[,1] s <- which(colSums(is.na(zz[,-1])) == 0) if (length(s) == 1) { out[[i]] <- x[s][[ dd[,s] ]] } else { ss <- x[s] for (j in 1:length(s)) { ss[j] = ss[j][[ dd[, s[j]] ]] } out[[i]] <- app(ss, fun) time(out[[i]]) <- tim } } out <- rast(out) if (filename != "") { out <- writeRaster(out, ...) } out } ) terra/R/predict.R0000644000175000017500000001357214201035747013512 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : August 2009 # Version 0.9 # License GPL v3 parfun <- function(cls, d, fun, model, ...) { nr <- nrow(d) nc <- length(cls) s <- split(d, rep(1:nc, each=ceiling(nr/nc), length.out=nr)) p <- parallel::clusterApply(cls, s, function(i, ...) fun(model, i, ...), ...) if (!is.null(dim(p[[1]]))) { do.call(rbind, p) } else { unlist(p) } } .runModel <- function(model, fun, d, nl, const, na.rm, index, cores=1, cls=NULL, ...) { if (!is.data.frame(d)) { d <- data.frame(d) } if (! is.null(const)) { for (i in 1:ncol(const)) { d <- cbind(d, const[,i,drop=FALSE]) } } if (na.rm) { n <- nrow(d) i <- rowSums(is.na(d)) == 0 d <- d[i,,drop=FALSE] if (nrow(d) > 0) { if (cores > 1) { r <- parfun(cls, d, fun, model, ...) } else { r <- fun(model, d, ...) } if (is.factor(r)) { r <- as.integer(r) } #how could it not be numeric? #else if (is.data.frame(r)) { # if (nrow(r) > 1) { # r <- apply(r, as.numeric) # } else { # r[] <- as.numeric(r) # } #} r <- as.matrix(r) if (!all(i)) { m <- matrix(NA, nrow=nl*n, ncol=ncol(r)) m[i,] <- r colnames(m) <- colnames(r) r <- m } } else { if (!is.null(index)) { r <- matrix(NA, nrow=nl*n, ncol=max(index)) } else { r <- matrix(NA, nrow=nl*n, ncol=1) } } } else { if (cores > 1) { r <- parfun(cls, d, fun, model, ...) } else { r <- fun(model, d, ...) } if (is.factor(r)) { r <- as.integer(r) } else if (is.data.frame(r)) { r <- sapply(r, as.numeric) } r <- as.matrix(r) } if (inherits(model, "gstat")) { nr <- max(nrow(d), 5) xy <- as.matrix(d[1:nr,1:2]) if (all(xy == r[1:nr, 1:2])) { r <- r[,-c(1:2)] # x, y } } if (!is.null(index)) { r <- r[, index,drop=FALSE] } r } .getFactors <- function(m, facts=NULL, lyrnms) { if (!is.null(facts)) { stopifnot(is.list(factors)) f <- names(factors) if (any(trimws(f) == "")) { error("predict", "all factors must be named") } } else if (inherits(m, "randomForest")) { f <- names(which(sapply(m$forest$xlevels, max) != "0")) if (length(f) > 0) { factors <- m$forest$xlevels[f] } } else if (inherits(m, "gbm")) { dafr <- m$gbm.call$dataframe i <- sapply(dafr, is.factor) if (any(i)) { j <- which(i) factors <- list() for (i in 1:length(j)) { factors[[i]] <- levels(dafr[[ j[i] ]]) } names(factors) <- colnames(dafr)[j] } } else { #glm and others try(factors <- m$xlevels, silent=TRUE) } if (!all(names(factors) %in% lyrnms)) { ff <- f[!(f %in% lyrnms)] error("predict", paste("factor name(s):", paste(ff, collapse=", "), " not in layer names")) } factors } setMethod("predict", signature(object="SpatRaster"), function(object, model, fun=predict, ..., factors=NULL, const=NULL, na.rm=FALSE, index=NULL, cores=1, cpkgs=NULL, filename="", overwrite=FALSE, wopt=list()) { nms <- names(object) if (length(unique(nms)) != length(nms)) { tab <- table(nms) error("predict", "duplicate names in SpatRaster: ", tab[tab>1]) } #factors should come with the SpatRaster #haveFactor <- FALSE #if (!is.null(factors)) { # factors <- .getFactors(model, factors, nms) # fnames <- names(f) # haveFactor <- TRUE #} nl <- 1 nc <- ncol(object) nr <- nrow(object) tomat <- FALSE readStart(object) on.exit(readStop(object)) testrow <- round(0.51*nr) rnr <- 1 if (nc==1) rnr <- min(nr, 20) - testrow + 1 d <- readValues(object, testrow, rnr, 1, nc, TRUE, TRUE) cn <- NULL if (!is.null(index)) { nl <- length(index) } else { allna <- FALSE if (na.rm) { allna <- all(is.na(d)) if (allna) { testrow <- ceiling(testrow - 0.25*nr) d <- readValues(object, testrow, rnr, 1, nc, TRUE, TRUE) allna <- all(is.na(d)) } if (allna) { testrow <- floor(testrow + 0.5*nr) if ((testrow + rnr) > nr) rnr = nr - testrow + 1 d <- readValues(object, testrow, rnr, 1, nc, TRUE, TRUE) allna <- all(is.na(d)) } if (allna && (ncell(object) < 1000)) { d <- readValues(object, 1, nr, 1, nc, TRUE, TRUE) allna <- all(is.na(d)) #if (allna) { # error("predict", "all predictor values are NA") #} } if (allna) { d <- spatSample(object, min(1000, ncell(object)), "regular") allna <- all(is.na(d)) } } if (!allna) { r <- .runModel(model, fun, d, nl, const, na.rm, index, ...) if (ncell(object) > 1) { nl <- ncol(r) cn <- colnames(r) } else { nl <- length(r) } } else { warn("predict", "Cannot determine the number of output variables. Assuming 1. Use argument 'index' to set it manually") } } out <- rast(object, nlyrs=nl) if (length(cn) == nl) names(out) <- make.names(cn, TRUE) if (cores > 1) { cls <- parallel::makeCluster(cores) on.exit(parallel::stopCluster(cls), add=TRUE) parallel::clusterExport(cls, c("model", "fun"), environment()) if (!is.null(cpkgs)) { parallel::clusterExport(cls, "cpkgs", environment()) parallel::clusterCall(cls, function() for (i in 1:length(cpkgs)) {library(cpkgs[i], character.only=TRUE) }) } dots <- list(...) if (length(dots) > 0) { nms <- names(dots) dotsenv <- new.env() lapply(1:length(dots), function(i) assign(nms[i], dots[[i]], envir=dotsenv)) parallel::clusterExport(cls, nms, dotsenv) } } else { cls <- NULL } b <- writeStart(out, filename, overwrite, wopt=wopt, n=max(nlyr(out), nlyr(object))*4) for (i in 1:b$n) { d <- readValues(object, b$row[i], b$nrows[i], 1, nc, TRUE, TRUE) r <- .runModel(model, fun, d, nl, const, na.rm, index, cores=cores, cls=cls, ...) writeValues(out, r, b$row[i], b$nrows[i]) } writeStop(out) return(out) } ) terra/R/plotExtent.R0000644000175000017500000000201014201035747014207 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : July 2019 # Version 1.0 # License GPL v3 setMethod("lines", signature(x="SpatExtent"), function(x, col="black", alpha=1, ...) { e <- as.vector(x) p <- rbind(c(e[1],e[3]), c(e[1],e[4]), c(e[2],e[4]), c(e[2],e[3]), c(e[1],e[3])) col <- .getCols(1, col, alpha) graphics::lines(p, col=col, ...) } ) setMethod("polys", signature(x="SpatExtent"), function(x, col="black", alpha=1, ...) { polys(as.polygons(x), col=col, alpha=alpha, ...) } ) setMethod("plot", signature(x="SpatExtent", y="missing"), function(x, ...) { test <- try(x$valid, silent=TRUE) if (inherits(test, "try-error")) { error("plot", "invalid SpatExtent") } plot(as.polygons(x), ...) } ) setMethod("points", signature(x="SpatExtent"), function(x, col="black", alpha=1, ...) { e <- as.vector(x) p <- rbind(c(e[1],e[3]), c(e[1],e[4]), c(e[2],e[4]), c(e[2],e[3]), c(e[1],e[3])) col <- .getCols(4, col, alpha) graphics::points(p, col=col, ...) } ) terra/R/click.R0000644000175000017500000000577014201035747013146 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : January 2009 - December 2011 # Version 1.0 # License GPL v3 #.getClicks <- function(...) { # res <- list() # while(TRUE) { # loc <- graphics::locator(1, ...) # if (is.null(loc)) break # res <- c(res, loc) # } # matrix(res, ncol=2, byrow=TRUE) #} .getCellFromClick <- function(x, n, type, id, ...) { #loc <- graphics::locator(n, type, ...) #xyCoords <- cbind(x=loc$x, y=loc$y) xyCoords <- RS_locator(n, type, ...) if (id) { text(xyCoords, labels=1:n) } cells <- cellFromXY(x, xyCoords) cells <- unique(stats::na.omit(cells)) if (length(cells) == 0 ) { error("click", "no valid cells selected") } cells } do_click <- function(type="p", id=FALSE, i=1, pch=20, ...) { p <- graphics::locator(1) if (is.null(p)) return(p) # ESC points(p$x, p$y, type=type, pch=pch, ...) if (id) { text(p$x, p$y, labels=i, pos=4, ...) } cbind(x=p$x, y=p$y) } setMethod("click", signature(x="missing"), function(x, n=10, id=FALSE, type="p", show=TRUE, ...) { #loc <- graphics::locator(n, type, ...) #cbind(x=loc$x, y=loc$y) n <- max(1, round(n)) X <- NULL for (i in 1:n) { x <- do_click(type=type, id=id, i=i, ...) if (is.null(x)) break X <- rbind(X, x) if (show) print(x); utils::flush.console() if (show) { on.exit(return(invisible(X))) } else { on.exit(return(X)) } } if (show) invisible(X) else X } ) setMethod("click", signature(x="SpatRaster"), function(x, n=10, id=FALSE, xy=FALSE, cell=FALSE, type="p", show=TRUE, ...) { n <- max(round(n), 1) values <- NULL for (i in 1:n) { p <- do_click(type=type, id=id, i=i, ...) if (is.null(p)) break celln <- cellFromXY(x, p) if (is.na(celln)) next value <- x[celln] if (cell) { value <- data.frame(cell=celln, value) } if (xy) { p <- xyFromCell(x, celln) colnames(p) <- c("x", "y") value <- data.frame(p, value) } if (show) { print(value) utils::flush.console() } if (is.null(dim(value))) { value <- matrix(value) colnames(value) <- names(x) } values <- rbind(values, value) if (show) { on.exit(return(invisible(values))) } else { on.exit(return(values)) } } if (show) { invisible(values) } else { values } }) setMethod("click", signature(x="SpatVector"), function(x, n=10, id=FALSE, xy=FALSE, type="p", show=TRUE, ...) { n <- max(round(n), 1) values <- xys <- NULL for (i in 1:n) { p <- do_click(type=type, id=id, i=i, ...) if (is.null(p)) break e <- extract(x, vect(p)) if (xy) { e <- cbind(e[,1], x=p$x, y=p$y, e[,-1,drop=FALSE]) } names(e)[1] <- "ID" if (show) { if (!id) { print(e[,-1]) } else { print(e) } utils::flush.console() } values <- rbind(values, e) if (show) { on.exit(return(invisible(values))) } else { on.exit(return(values)) } } if (show) { invisible(values) } else { values } } ) terra/R/Zdeprecated.R0000644000175000017500000000277614201035747014316 0ustar nileshnilesh setMethod ("setCats", "SpatRaster", function(x, ...) { warn("setCats", "this function will be removed. You can use 'set.cats' instead") set.cats(x, ...) } ) if (!isGeneric("RGB2col")) {setGeneric("RGB2col", function(x, ...) standardGeneric("RGB2col"))} setMethod("RGB2col", signature(x="SpatRaster"), function(x, alpha=FALSE, filename="", overwrite=FALSE, ...) { warn("RGB2col", "this function will be removed. You can use 'colorize' instead") rgb2col(x, alpha=FALSE, filename="", overwrite=FALSE, ...) } ) ## spatstat conflicts if (!isGeneric("area")) {setGeneric("area", function(x, ...) standardGeneric("area"))} setMethod("area", signature(x="SpatRaster"), function(x, sum=TRUE, correct=FALSE, mask=FALSE, filename="", ...) { if (!sum) { error("area", 'area(x, sum=FALSE) will be removed. Use "cellSize(x)"') } else { error("area", 'area(x, sum=TRUE) will be removed. Use "expanse(x)" or "global(cellSize(x), "sum")"') } } ) setMethod("area", signature(x="SpatVector"), function(x, ...) { error("area", 'area was removed. Use "expanse(x)"') } ) # dplyr conflict if (!isGeneric("src")) { setGeneric("src", function(x, ...) standardGeneric("src")) } setMethod("src", signature(x="ANY"), function(x, ...) { warn("src", '"src" will be removed. It has been renamed to "sprc"') sprc(x, ...) } ) ##ggplot2 conflict arrow <- function(...) { warn("arrow", '"arrow" will be removed. It has been renamed to "north"') north(...) } terra/R/plot_scale.R0000644000175000017500000001754514201035747014211 0ustar nileshnilesh .assume_lonlat <- function(pr) { (pr$usr[1] > -181) && (pr$usr[2] < 181) && (pr$yaxp[1] > -200) && (pr$yaxp[2] < 200) } .get_dd <- function(pr, lonlat, d=NULL) { if (lonlat) { lat <- mean(pr$yaxp[1:2]) if (is.null(d)) { dx <- (pr$usr[2] - pr$usr[1]) / 6 d <- as.vector(distance(cbind(0, lat), cbind(dx, lat), TRUE)) d <- signif(d / 1000, 2) } p <- cbind(0, lat) dd <- .destPoint(p, d * 1000) dd <- dd[1,1] } else { if (is.null(d)) { d <- (pr$usr[2] - pr$usr[1]) / 6 digits <- floor(log10(d)) + 1 d <- round(d, -(digits-1)) } dd <- d } dd } .get_xy <- function(xy, dx=0, dy=0, pr, defpos="bottomleft", caller="") { if(is.null(xy)) { xy <- defpos } if (!is.character(xy)) { return( cbind(xy[1], xy[2]) ) } xy <- tolower(xy) parrange <- c(pr$usr[2] - pr$usr[1], pr$usr[4] - pr$usr[3]) pad=c(5,5) / 100 if (xy == "bottom") { xy <- c(pr$usr[1]+0.5*parrange[1]-0.5*dx, pr$usr[3]+(pad[2]*parrange[2])) + c(0,dy) } else if (xy == "bottomleft") { xy <- c(pr$usr[1]+(pad[1]*parrange[1]), pr$usr[3]+(pad[2]*parrange[2])) + c(0,dy) } else if (xy == "bottomright") { xy <- c(pr$usr[2]-(pad[1]*parrange[1]), pr$usr[3]+(pad[2]*parrange[2])) - c(dx,-dy) } else if (xy == "topright") { xy <- c(pr$usr[2]-(pad[1]*parrange[1]), pr$usr[4]-(pad[2]*parrange[2])) - c(dx,dy) } else if (xy == "top") { xy <- c(pr$usr[1]+0.5*parrange[1]-0.5*dx, pr$usr[4]-(pad[2]*parrange[2])) - c(0,dy) } else if (xy == "topleft") { xy <- c(pr$usr[1]+(pad[1]*parrange[1]), pr$usr[4]-(pad[2]*parrange[2])) - c(0,dy) } else if (xy == "left") { xy <- c(pr$usr[1]+(pad[1]*parrange[1]), pr$usr[3]+0.5*parrange[2]-0.5*dy) } else if (xy == "right") { xy <- c(pr$usr[2]-(pad[1]*parrange[1])-dx, pr$usr[3]+0.5*parrange[2]-0.5*dy) } else { error(caller, 'xy must be a coordinate pair (two numbers) or one of "bottomleft", "bottom", "bottomright", topleft", "top", "topright"') } xy } .destPoint <- function (p, d, b=90, r=6378137) { toRad <- pi/180 lon1 <- p[, 1] * toRad lat1 <- p[, 2] * toRad b <- b * toRad lat2 <- asin(sin(lat1) * cos(d/r) + cos(lat1) * sin(d/r) * cos(b)) lon2 <- lon1 + atan2(sin(b) * sin(d/r) * cos(lat1), cos(d/r) - sin(lat1) * sin(lat2)) lon2 <- (lon2 + pi)%%(2 * pi) - pi cbind(lon2, lat2)/toRad } add_N <- function(x, y, asp, label, type=0, user="", angle=0, cex=1, srt=0, xpd=TRUE, ...) { type <- type[1] if (type == 0) { symbol = user[1] } else if (type == 2) { symbol = "\u27A2" } else if (type == 3) { symbol = "\u2799" } else if (type == 4) { symbol = "\u27B2" } else if (type == 5) { symbol = "\u27BE" } else if (type == 6) { symbol = "\u27B8" } else if (type == 7) { symbol = "\u27BB" } else if (type == 8) { symbol = "\u27B5" } else if (type == 9) { symbol = "\u279F" } else if (type == 10) { symbol = "\u261B" } else if (type == 11) { symbol = "\u2708" } else { symbol = "\u2629"} if (type == 11) { rangle <- 45 - angle mcex <- 1.5 } else { rangle <- 90 - angle mcex <- 3 } text(x, y, symbol, cex=cex*mcex, srt=rangle, xpd=xpd, ...) xs <- graphics::strwidth(symbol,cex=cex*3) ys <- graphics::strheight(symbol,cex=cex*3) b <- pi * angle / 180 rxs <- (abs(xs * cos(b)) + abs(ys * sin(b)))# / asp rys <- (abs(xs * sin(b)) + abs(ys * cos(b)))# * asp # xoff <- (rxs - xs) / 2 # yoff <- rys + 0.05 * graphics::strheight(label,cex=cex) xoff = 0.1 * rxs yoff = 0.8 * rys * max(0.5, abs(cos(angle))) if (type == 4) { .halo(x+xoff, y-0.2*yoff, label, cex = cex, srt = srt, xpd = xpd, ...) } else if (type == 10) { .halo(x+xoff, y-yoff, label, cex = cex, srt = srt, xpd = xpd, ...) } else { text(x+xoff, y+yoff, label, cex = cex, srt = srt, xpd = xpd, ...) } } north <- function(xy=NULL, type=1, label="N", angle=0, d, head=0.1, xpd=TRUE, ...) { pr <- graphics::par() pa <- c(pr$usr[2] - pr$usr[1], pr$usr[4] - pr$usr[3]) asp <- pa[2]/pa[1] if (missing(d)) { d <- 0.07 * pa[2] } xy <- .get_xy(xy, 0, d, pr, "topright", caller="arrow") if (inherits(type, "character")) { usertype <- type type = 0 } else { type <- round(type) usertype <- "" } if (type == 1) { if (angle != 0) { b <- angle * pi / 180; p2 <- xy + c(d * sin(b), d * cos(b)) b <- b + pi p1 <- xy + c(d * sin(b), d * cos(b)) if ((p2[1] - p1[1]) > (d/asp)) { m <- xy[1] #p1[1] + (p2[1] - p1[1]) / 2 slope = (p2[2] - p1[2])/(p2[1] - p1[1]) newx <- m - 0.5 * d / asp p1[2] <- p1[2] + (newx-p1[1]) * slope p1[1] <- newx newx <- m + 0.5 * d / asp p2[2] <- p2[2] - (p2[1]-newx) * slope p2[1] <- newx } } else { p1 <- xy - c(0,d) p2 <- xy + c(0,d) } lwd <- list(...)$lwd + 2 if (is.null(lwd)) lwd <- 3 graphics::arrows(p1[1], p1[2], p2[1], p2[2], length=head, lwd=lwd, col="white", xpd=xpd) graphics::arrows(p1[1], p1[2], p2[1], p2[2], length=head, xpd=xpd, ...) if (label != "") { if (is.null(list(...)$hw)) { .halo(xy[1], xy[2], label, hw=.2, xpd=xpd, ... ) } else { .halo(xy[1], xy[2], label, xpd=xpd, ... ) } } } else { add_N(xy[1], xy[2], asp=asp, label=label, angle=angle, type=type, user=usertype, xpd=xpd, ...) } } sbar <- function(d, xy=NULL, type="line", divs=2, below="", lonlat=NULL, label, adj=c(0.5, -1), lwd=2, xpd=TRUE, ...){ stopifnot(type %in% c("line", "bar")) pr <- graphics::par() if (is.null(lonlat)) { lonlat <- .assume_lonlat(pr) } if (missing(d)) { label <- NULL d <- NULL } dd <- .get_dd(pr, lonlat, d) if (is.null(d)) d <- dd xy <- .get_xy(xy, dd, 0, pr, "bottomleft", caller="sbar") if (type == "line") { lines(matrix(c(xy[1], xy[2], xy[1]+dd, xy[2]), byrow=T, nrow=2), lwd=lwd, xpd=xpd, ...) if (missing(label)) { label <- paste(d) } if (is.null(label)) { label <- paste(d) } if (missing(adj)) { adj <- c(0.5, -0.2-lwd/20 ) } if (length(label) == 1) label =c("", label, "") text(xy[1], xy[2],labels=label[1], xpd=xpd, adj=adj,...) text(xy[1]+0.5*dd, xy[2],labels=label[2], xpd=xpd, adj=adj,...) text(xy[1]+dd, xy[2],labels=label[3], xpd=xpd, adj=adj,...) xy[2] <- xy[2] - dd/10 } else if (type == "bar") { stopifnot(divs > 0) if (missing(adj)) { adj <- c(0.5, -1 ) } lwd <- dd / 25 if (divs==2) { half <- xy[1] + dd / 2 graphics::polygon(c(xy[1], xy[1], half, half), c(xy[2], xy[2]+lwd, xy[2]+lwd, xy[2]), col="white", xpd=xpd) graphics::polygon(c(half, half, xy[1]+dd, xy[1]+dd ), c(xy[2], xy[2]+lwd, xy[2]+lwd, xy[2]), col="black", xpd=xpd) if (missing(label)) { label <- c("0", "", d) } if (is.null(label)) { label <- c("0", "", d) } text(xy[1], xy[2],labels=label[1], xpd=xpd, adj=adj,...) text(xy[1]+0.5*dd, xy[2],labels=label[2], xpd=xpd, adj=adj,...) text(xy[1]+dd, xy[2],labels=label[3], xpd=xpd, adj=adj,...) } else { q1 <- xy[1] + dd / 4 half <- xy[1] + dd / 2 q3 <- xy[1] + 3 * dd / 4 end <- xy[1] + dd graphics::polygon(c(xy[1], xy[1], q1, q1), c(xy[2], xy[2]+lwd, xy[2]+lwd, xy[2]), col="white", xpd=xpd) graphics::polygon(c(q1, q1, half, half), c(xy[2], xy[2]+lwd, xy[2]+lwd, xy[2]), col="black", xpd=xpd) graphics::polygon(c(half, half, q3, q3 ), c(xy[2], xy[2]+lwd, xy[2]+lwd, xy[2]), col="white", xpd=xpd) graphics::polygon(c(q3, q3, end, end), c(xy[2], xy[2]+lwd, xy[2]+lwd, xy[2]), col="black", xpd=xpd) if (missing(label)) { label <- c("0", round(0.5*d), d) } if (is.null(label)) { label <- c("0", round(0.5*d), d) } text(xy[1], xy[2], labels=label[1], xpd=xpd, adj=adj, ...) text(half, xy[2], labels=label[2], xpd=xpd, adj=adj,...) text(end, xy[2],labels=label[3], xpd=xpd, adj=adj,...) } } if (below != "") { adj[2] <- -adj[2] text(xy[1]+(0.5*dd), xy[2], xpd=xpd, labels=below, adj=adj,...) } } terra/R/lapp.R0000644000175000017500000001156614201035747013015 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : May 2020 # Version 1.0 # License GPL v3 .lapp_test <- function(v, fun, usenames, ...) { # figure out the shape of the output nms = "" nr <- nrow(v) if (!usenames) colnames(v) <- NULL vtst <- try(do.call(fun, c(v, list(...))), silent=FALSE) if (inherits(vtst, "try-error")) { nl <- -1 } if (length(vtst) >= nr) { if ((length(vtst) %% nr) == 0) { nl <- length(vtst) / nr } else { nl <- -1 } } else { nl <- -1 } if (is.matrix(vtst)) { nms <- colnames(vtst) } list(nl=nl, names=nms) } setMethod("lapp", signature(x="SpatRaster"), function(x, fun, ..., usenames=FALSE, cores=1, filename="", overwrite=FALSE, wopt=list()) { fun <- match.fun(fun) dots <- list(...) if (any(sapply(dots, function(i) inherits(i, "SpatRaster")))) { error("lapp", "only 'x' can be a SpatRaster") # otherwise .lapp_test may crash! } if (usenames) { fnames <- names(formals(fun)) x <- x[[names(x) %in% fnames]] } doclust <- FALSE if (inherits(cores, "cluster")) { doclust <- TRUE ncores <- length(cores) } else if (cores > 1) { doclust <- TRUE ncores <- cores cores <- parallel::makeCluster(cores) on.exit(parallel::stopCluster(cores), add=TRUE) } readStart(x) on.exit(readStop(x), add=TRUE) ncx <- ncol(x) v <- readValues(x, round(0.51*nrow(x)), 1, 1, ncx, dataframe=TRUE) test <- .lapp_test(v, fun, usenames, ...) if (test$nl < 1) error("lapp", "I do not like 'fun' :(") out <- rast(x, nlyrs=test$nl) if (length(test$names == test$nl)) { if (is.null(wopt$names)) wopt$names <- test$names } b <- writeStart(out, filename, overwrite, wopt=wopt) expected <- test$nl * ncx if (doclust) { cfun <- function(i, ...) do.call(fun, i, ...) parallel::clusterExport(cores, "cfun", environment()) for (i in 1:b$n) { v <- readValues(x, b$row[i], b$nrows[i], 1, ncx, dataframe=TRUE) if (!usenames) colnames(v) <- NULL v <- split(v, rep(1:ncores, each=ceiling(nrow(v) / ncores))[1:nrow(v)]) v <- unlist(parallel::parLapply(cores, v, cfun)) if (length(v) != (expected * b$nrows[i])) { out <- writeStop(out) error("lapp", "output length of fun is not correct") } writeValues(out, v, b$row[i], b$nrows[i]) } } else { for (i in 1:b$n) { v <- readValues(x, b$row[i], b$nrows[i], 1, ncx, dataframe=TRUE) if (!usenames) colnames(v) <- NULL v <- do.call(fun, c(v, list(...))) if (length(v) != (expected * b$nrows[i])) { out <- writeStop(out) error("lapp", "output length of fun is not correct") } writeValues(out, v, b$row[i], b$nrows[i]) } } out <- writeStop(out) return(out) } ) .lapp_test_stack <- function(v, fun, recycle, ...) { # figure out the shape of the output nms = "" nr <- nrow(v[[1]]) if (recycle) { v <- lapply(v, as.vector) } vtst <- try(do.call(fun, c(v, list(...))), silent=FALSE) if (inherits(vtst, "try-error")) { nl <- -1 } if (length(vtst) >= nr) { if ((length(vtst) %% nr) == 0) { nl <- length(vtst) / nr } else { nl <- -1 } } else { nl <- -1 } if (is.matrix(vtst)) { nms <- colnames(vtst) } list(nl=nl, names=nms) } setMethod("lapp", signature(x="SpatRasterDataset"), function(x, fun, ..., recycle=FALSE, filename="", overwrite=FALSE, wopt=list()) { fun <- match.fun(fun) dots <- list(...) if (any(sapply(dots, function(i) inherits(i, "SpatRasterDataset")))) { error("lapp", "only 'x' can be a SpatRasterDataset") # otherwise .lapp_test_stack fails } ncx <- ncol(x[1]) nrx <- nrow(x[1]) readStart(x) on.exit(readStop(x)) v <- lapply(1:length(x), function(i) readValues(x[i], round(0.51*nrx), 1, 1, ncx, mat=TRUE)) test <- .lapp_test_stack(v, fun, recycle, ...) if (test$nl < 1) error("lapp", "cannot use 'fun'") out <- rast(x[1]) nlyr(out) <- test$nl if (length(test$names == test$nl)) { if (is.null(wopt$names)) wopt$names <- test$names } nltot <- sum(nlyr(x)) + nlyr(out) fact <- max(4, 4 * nltot / nlyr(out)) b <- writeStart(out, filename, overwrite, wopt=wopt, n=fact) # nr <- b$nrows[i] * ncol(out) # splits <- rep(1:ncores, each=ceiling(nr) / ncores)[1:nr] # v <- vector(mode = "list", length = ncores) # for (j in 1:length(x)) { # vv <- readValues(x[j], b$row[i], b$nrows[i], 1, ncx, mat=TRUE) # for (k in 1:ncores) { # v[[k]][[j]] <- vv[splits==k,] # } # } # if (recycle) { # for (k in 1:ncores) { # v[[k]] <- lapply(v[[k]], as.vector) # } # } # if (length(list(...) > 0)) { # v[[k]] <- c(v[[k]], list(...)) # } for (i in 1:b$n) { v <- lapply(1:length(x), function(s) readValues(x[s], b$row[i], b$nrows[i], 1, ncx, mat=TRUE)) if (recycle) { v <- lapply(v, as.vector) } v <- do.call(fun, c(v, list(...))) writeValues(out, v, b$row[i], b$nrows[i]) } out <- writeStop(out) return(out) } ) terra/R/init.R0000644000175000017500000000177214201035747013022 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : May 2019 # Version 1.0 # License GPL v3 setMethod("init", signature(x="SpatRaster"), function(x, fun, filename="", ...) { opt <- spatOptions(filename, ...) x <- rast(x) if (is.character(fun)) { x <- rast(x, 1) fun <- fun[1] if (fun %in% c("x", "y", "row", "col", "cell", "chess")) { x@ptr <- x@ptr$initf(fun, TRUE, opt) messages(x, "init") } else if (is.na(fun)) { x@ptr <- x@ptr$initv(as.numeric(NA), opt) messages(x, "init") } else { error("init", "unknown function") } } else if (is.numeric(fun) || is.logical(fun)) { x@ptr <- x@ptr$initv(fun, opt) messages(x, "init") } else { nc <- ncol(x) b <- writeStart(x, filename, ...) for (i in 1:b$n) { n <- b$nrows[i] * nc; r <- fun(n) if (length(r) != n) { error("init","the number of values returned by 'fun' is not correct") } writeValues(x, r, b$row[i], b$nrows[i]) } writeStop(x) } } ) terra/R/time.R0000644000175000017500000000420514201035747013007 0ustar nileshnilesh# Author: Robert J. Hijmans # Date: October 2018 # Version 1.0 # License GPL v3 setMethod("time", signature(x="SpatRaster"), function(x) { if (!x@ptr$hasTime) { return(rep(NA, nlyr(x))) } d <- x@ptr$time tstep <- x@ptr$timestep if (tstep == "seconds") { strptime("1970-01-01", "%Y-%m-%d", tz = "UTC") + d } else if (tstep == "days") { d <- strptime("1970-01-01", "%Y-%m-%d", tz = "UTC") + d as.Date(d) #} else if (tstep == "months") { #} else if (tstep == "years") { } else { # raw d } } ) setMethod("time<-", signature(x="SpatRaster"), function(x, value) { if (inherits(value, "Date")) { value <- as.POSIXlt(value) tstep <- "days" } else if (inherits(value, "POSIXt")) { tstep <- "seconds" } else if (is.null(value)) { x@ptr$setTime(0[0], "remove") return(x) } else { tstep <- "raw" } if (!x@ptr$setTime(as.numeric(value), tstep)) { error("time<-", "cannot set these values") } return(x) } ) setMethod("depth", signature(x="SpatRaster"), function(x) { x@ptr$depth } ) setMethod("depth<-", signature(x="SpatRaster"), function(x, value) { if (is.null(value)) { x@ptr$setTime(0[0]) return(x) } value <- as.numeric(value) if (! x@ptr$setDepth(value)) { error("depth<-", "cannot set these values") } return(x) } ) setMethod("linearUnits", signature(x="SpatRaster"), function(x) { .getLinearUnits(crs(x)) } ) setMethod("linearUnits", signature(x="SpatVector"), function(x) { .getLinearUnits(crs(x)) } ) setMethod("units", signature(x="SpatRaster"), function(x) { x@ptr$units } ) setMethod("units<-", signature(x="SpatRaster"), function(x, value) { value <- as.character(value) if (! x@ptr$set_units(value)) { error("units<-", "cannot set these values") } return(x) } ) setMethod("units", signature(x="SpatRasterDataset"), function(x) { x@ptr$units } ) setMethod("units<-", signature(x="SpatRasterDataset"), function(x, value) { value <- as.character(value) x@ptr$units <- value return(x) } ) terra/R/subset.R0000644000175000017500000001101014201035747013346 0ustar nileshnilesh# Authors: Robert J. Hijmans # Date : October 2018 # Version 1.0 # License GPL v3 positive_indices <- function(i, n, caller=" [ ") { if (!(all(i <= 0) || all(i >= 0))) { error(caller, "you cannot mix positive and negative indices") } i <- stats::na.omit(i) (1:n)[i] } setMethod("subset", signature(x="SpatRaster"), function(x, subset, filename="", overwrite=FALSE, ...) { if (is.character(subset)) { i <- match(subset, names(x)) } else { i <- as.integer(subset) i[(i<1) | (i>nlyr(x))] <- NA } if (any(is.na(i))) { error("subset", paste("undefined layer(s) selected:", paste(subset[is.na(i)], collapse=", "))) } opt <- spatOptions(filename, overwrite, ...) x@ptr <- x@ptr$subset(i-1, opt) messages(x, "subset") return(x) } ) setMethod("[", c("SpatRaster", "SpatVector", "missing"), function(x, i, j, ... ,drop=TRUE) { if (drop) { extract(x, i, data.frame=TRUE)[ , -1, drop=FALSE] } else { crop(x, i, mask=TRUE) } } ) ## expression matching setMethod("[", c("SpatRaster", "character", "missing"), function(x, i, j, ... ,drop=TRUE) { i <- grep(i, names(x)) subset(x, i, ...) } ) ## exact matching setMethod("[[", c("SpatRaster", "character", "missing"), function(x, i, j, ... ,drop=TRUE) { subset(x, i, ...) }) setMethod("$", "SpatRaster", function(x, name) { subset(x, name) } ) setMethod("[[", c("SpatRaster", "logical", "missing"), function(x, i, j, ... ,drop=TRUE) { subset(x, which(i), ...) }) setMethod("[[", c("SpatRaster", "numeric", "missing"), function(x, i, j, ... ,drop=TRUE) { i <- positive_indices(i, nlyr(x), " [[ ") subset(x, i, ...) }) setMethod("subset", signature(x="SpatVector"), function(x, subset, drop=FALSE) { x <- x[which(as.vector(subset)), , drop=drop] messages(x, "subset") } ) .subset_cols <- function(x, subset, drop=FALSE) { if (is.character(subset)) { i <- stats::na.omit(match(subset, names(x))) } else { i <- positive_indices(subset, ncol(x), "subset") } if (length(i)==0) { i <- 0 } if (length(i) < length(subset)) { warn(" [ ", "invalid columns omitted") } x@ptr <- x@ptr$subset_cols(i-1) x <- messages(x, "subset") if (drop) { # drop geometry .getSpatDF(x@ptr$df) } else { x } } setMethod("[", c("SpatVector", "numeric", "missing"), function(x, i, j, ... , drop=FALSE) { i <- positive_indices(i, nrow(x), "'['") x@ptr <- x@ptr$subset_rows(i-1) x <- messages(x, "[") if (drop) { as.data.frame(x) } else { x } }) setMethod("[", c("SpatVector", "logical", "missing"), function(x, i, j, ... , drop=FALSE) { i <- which(i) x@ptr <- x@ptr$subset_rows(i-1) x <- messages(x, "[") if (drop) { as.data.frame(x) } else { x } }) setMethod("[", c("SpatVector", "numeric", "numeric"), function(x, i, j, ... , drop=FALSE) { i <- positive_indices(i, nrow(x), "'['") j <- positive_indices(j, ncol(x), "'['") p <- x@ptr$subset_rows(i-1) x@ptr <- p$subset_cols(j-1) x <- messages(x, "'['") if (drop) { as.data.frame(x) } else { x } }) setMethod("[", c("SpatVector", "missing", "numeric"), function(x, i, j, ... , drop=FALSE) { j <- positive_indices(j, ncol(x), "'['") x@ptr <- x@ptr$subset_cols(j-1) x <- messages(x, "[") if (drop) { as.data.frame(x) } else { x } }) setMethod("[", c("SpatVector", "missing", "character"), function(x, i, j, ... , drop=FALSE) { if (j[1] == "") { jj <- 0 } else { jj <- match(j, names(x)) if (any(is.na(jj))) { mis <- paste(j[is.na(jj)], collapse=", ") error(" x[,j] ", paste("name(s) not in x:", mis)) } if (length(jj) == 0) { jj <- 0 } } x[,jj,drop=drop] }) setMethod("[", c("SpatVector", "numeric", "character"), function(x, i, j, ... , drop=FALSE) { j <- stats::na.omit(match(j, names(x))) if (length(j) == 0) j <- 0 x <- x[i,j,drop=drop] }) setMethod("[", c("SpatVector", "logical", "character"), function(x, i, j, ... , drop=FALSE) { i <- which(i) x[i,j,drop=drop] }) setMethod("[", c("SpatVector", "logical", "numeric"), function(x, i, j, ... , drop=FALSE) { i <- which(i) x[i,j,drop=drop] }) setMethod("[", c("SpatVector", "missing", "missing"), function(x, i, j, ... , drop=FALSE) { if (drop) { values(x) } else { x } }) setMethod("[", c("SpatVector", "matrix", "missing"), function(x, i, j, ... , drop=FALSE) { x[i[,1]] }) setMethod("[", c("SpatVector", "data.frame", "missing"), function(x, i, j, ... , drop=FALSE) { x[i[,1]] }) terra/R/SpatVectorCollection.R0000644000175000017500000000472214201035747016163 0ustar nileshnilesh setMethod("length", signature(x="SpatVectorCollection"), function(x) { x@ptr$size() } ) setMethod("svc", signature(x="missing"), function(x) { v <- methods::new("SpatVectorCollection") v@ptr <- SpatVectorCollection$new() v } ) setMethod("svc", signature(x="SpatVector"), function(x, ...) { r <- methods::new("SpatVectorCollection") r@ptr <- SpatVectorCollection$new() r@ptr$push_back(x@ptr) dots <- list(...) if (length(dots) > 0) { for (i in 1:length(dots)) { if (inherits(dots[[i]], "SpatVector")) { r@ptr$push_back(dots[[i]]@ptr) } else { warn("svc", "cannot add objects of class: ", class(dots[[i]])) } } } messages(r, "svc") } ) setMethod("svc", signature(x="list"), function(x) { r <- methods::new("SpatVectorCollection") r@ptr <- SpatVectorCollection$new() for (i in seq_along(x)) { if (inherits(x[[i]], "SpatVector")) { r@ptr$push_back(x[[i]]@ptr) } } messages(r, "svc") } ) setReplaceMethod("[", c("SpatVectorCollection", "numeric", "missing"), function(x, i, j, value) { stopifnot(inherits(value, "SpatVector")) if (any(!is.finite(i)) || any(i<1)) { error("`[<-`", "invalid index") } i <- sort(i) for (j in i) { if (j == (length(x)+1)) { x@ptr$push_back(value@ptr) } else { x@ptr$replace(value@ptr, j-1) } } messages(x, "`[<-`") } ) setMethod("[", c("SpatVectorCollection", "numeric", "missing"), function(x, i, j, ... ,drop=TRUE) { if (i<0) {i <- (1:length(x))[i]} if (drop && (length(i) == 1)) { ptr <- x@ptr$get(i-1) x <- methods::new("SpatVector") x@ptr <- ptr } else { x@ptr <- x@ptr$subset(i-1) } messages(x, "`[`") }) setMethod("[[", c("SpatVectorCollection", "numeric", "missing"), function(x, i, j, ... ,drop=TRUE) { x[i,drop=drop] }) setMethod("c", signature(x="SpatVector"), function(x, ...) { svc(x, ...) } ) setMethod("c", signature(x="SpatVectorCollection"), function(x, ...) { x@ptr <- x@ptr$subset(0:(x@ptr$size()-1) ) ## deep copy dots <- list(...) for (i in seq_along(dots)) { if (inherits(dots[[i]], "SpatVectorCollection")) { for (j in 1:length(dots[[i]])) { x@ptr$push_back(dots[[i]][[j]]@ptr) } } else if (inherits(dots[[i]], "SpatVector")) { x@ptr$push_back(dots[[i]]@ptr) } else { error("c", "arguments must be SpatVector or SpatVectorCollection") } } messages(x, "c") } ) terra/R/plot2rasters.R0000644000175000017500000001011414201035747014511 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : June 2019 # Version 1.0 # License GPL v3 .scatterPlotRaster <- function(x, y, maxcell=100000, warn=TRUE, cex, xlab, ylab, nc, nr, maxnl=16, main, add=FALSE, gridded=FALSE, ncol=25, nrow=25, ...) { compareGeom(x, y, lyrs=FALSE, crs=FALSE, warncrs=FALSE, ext=TRUE, rowcol=TRUE, res=FALSE) nlx <- nlyr(x) nly <- nlyr(y) maxnl <- max(1, round(maxnl)) nl <- max(nlx, nly) if (nl > maxnl) { nl <- maxnl if (nlx > maxnl) { x <- x[[1:maxnl]] nlx <- maxnl } if (nly > maxnl) { y <- y[[1:maxnl]] nly <- maxnl } } if (missing(main)) { main <- "" } if (missing(xlab)) { ln1 <- names(x) } else { ln1 <- xlab if (length(ln1) == 1) { ln1 <- rep(ln1, nlx) } } if (missing(ylab)) { ln2 <- names(y) } else { ln2 <- ylab if (length(ln1) == 1) { ln2 <- rep(ln2, nly) } } cells <- ncell(x) if (gridded) { # if ((ncell(x) * (nlx + nly)) < .maxmemory()) { if ((ncell(x) * (nlx + nly)) < 1000000) { maxcell <- ncell(x) } } x <- as.matrix(spatSample(c(x,y), size=maxcell, method="regular", as.raster=FALSE)) # y <- as.matrix(spatSample(y, size=maxcell, method="regular", as.raster=FALSE)) y <- x[,c((nlx+1):ncol(x))] x <- x[,1:nlx] if (warn & (NROW(x) < cells)) { warn("plot", 'plot used a sample of ', round(100*NROW(x)/cells, 1), '% of the cells. You can use "maxcell" to increase the sample)') } if (missing(cex)) { if (NROW(x) < 100) { cex <- 1 } else if (NROW(x) < 1000) { cex <- 0.5 } else { cex <- 0.2 } } if (nlx != nly) { # recycling d <- cbind(as.vector(x), as.vector(y)) x <- matrix(d[,1], ncol=nl) y <- matrix(d[,2], ncol=nl) lab <- vector(length=nl) lab[] <- ln1 ln1 <- lab lab[] <- ln2 ln2 <- lab } if (nl > 1) { old.par <- graphics::par(no.readonly = TRUE) on.exit(graphics::par(old.par)) graphics::par(mfrow=c(nr, nc), mar=c(4, 4, 2, 2)) if (! gridded) { if (add) { for (i in 1:nl) { graphics::points(x[,i], y[,i], cex=cex, ...) } } else { for (i in 1:nl) { plot(x[,i], y[,i], cex=cex, xlab=ln1[i], ylab=ln2[i], main=main[i], ...) } } } else { for (i in 1:nl) { .plotdens(x[,i], y[,i], nc=ncol, nr=nrow, main=main[i], xlab=ln1[i], ylab=ln2[i], add=add, ...) } } } else { if (! gridded) { if (add) { graphics::points(x, y, cex=cex, ...) } else { plot(x, y, cex=cex, xlab=ln1[1], ylab=ln2[1], main=main[1], ...) } } else { .plotdens(x, y, nc=ncol, nr=nrow, main=main[1], xlab=ln1[1], ylab=ln2[1], ...) } } } setMethod("plot", signature(x="SpatRaster", y="SpatRaster"), function(x, y, maxcell=100000, warn=TRUE, nc, nr, maxnl=16, gridded=FALSE, ncol=25, nrow=25, ...) { nl <- max(nlyr(x), nlyr(y)) if (missing(nc)) { nc <- ceiling(sqrt(nl)) } else { nc <- max(1, min(nl, round(nc))) } if (missing(nr)) { nr <- ceiling(nl / nc) } else { nr <- max(1, min(nl, round(nr))) nc <- ceiling(nl / nr) } .scatterPlotRaster(x, y, maxcell=maxcell, warn=warn, nc=nc, nr=nr, maxnl=maxnl, gridded=gridded, ncol=ncol, nrow=nrow, ...) } ) .plotdens <- function(x, y, nc, nr, xlim=NULL, ylim=NULL, asp=NULL, ...) { xy <- stats::na.omit(cbind(x,y)) if (nrow(xy) == 0) { error("plot (density)", "only NA values (in this sample?)") } r <- apply(xy, 2, range) rx <- r[,1] if (rx[1] == rx[2]) { rx[1] <- rx[1] - 0.5 rx[2] <- rx[2] + 0.5 } ry <- r[,2] if (ry[1] == ry[2]) { ry[1] <- ry[1] - 0.5 ry[2] <- ry[2] + 0.5 } out <- rast(xmin=rx[1], xmax=rx[2], ymin=ry[1], ymax=ry[2], ncol=nc, nrow=nr, crs="+proj=utm +zone=1 +datum=WGS84") colnames(xy) <- c("x", "y") out <- rasterize(vect(xy), out, fun=function(x, ...) length(x), background=0) if (!is.null(xlim) | !is.null(ylim)) { if (is.null(xlim)) xlim <- c(xmin(x), xmax(x)) if (is.null(ylim)) ylim <- c(ymin(x), ymax(x)) e <- extent(xlim, ylim) out <- extend(crop(out, e), e, value=0) } plot(out, maxcell=nc*nr, asp=asp, ...) } terra/R/ifelse.R0000644000175000017500000000244414201035747013323 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : May 2019 # Version 1.0 # License GPL v3 setMethod("ifel", signature(test="SpatRaster"), function(test, yes, no, filename="", ...) { no_num <- FALSE yes_num <- FALSE if (!inherits(no, "SpatRaster")) { # logical includes default NA if (!(is.numeric(no) || is.logical(no))) { error("ifel", "argument 'no' must be a SpatRaster, numeric or logical") } if (length(no) > 1) warn("ifel", 'only the first element of "no" is used') no <- no[1] no_num <- TRUE } if (!inherits(yes, "SpatRaster")) { if (!(is.numeric(yes) || is.logical(yes))) { error("ifel", "argument 'yes' must be a SpatRaster, numeric or logical") } if (length(yes) > 1) warn("ifel", 'only the first element of "yes" is used') yes <- yes[1] yes_num <- TRUE } test <- as.logical(test) if (no_num & yes_num) { return (classify(test, rbind(c(1, yes), c(0, no)), filename=filename, ...)) } if (no_num) { no <- classify(test, rbind(c(0, no), c(1, NA))) } else { no <- mask(no, test, maskvalues=TRUE) } if (yes_num) { yes <- classify(test, rbind(c(1, yes), c(0, NA))) } else { yes <- mask(yes, test, maskvalues=FALSE) } cover(no, yes, values=NA, filename=filename, ...) } ) terra/R/plot_legend.R0000644000175000017500000001746014201035747014354 0ustar nileshnilesh .get_breaks <- function(x, n, method, r=NULL) { if (is.function(method)) { if (!is.null(r)) { x[xr[2]] <- NA } breaks <- method(x) } else if (method=="cases") { if (!is.null(r)) { x[xr[2]] <- NA } n <- n+1 i <- seq(0, 1, length.out=n) breaks <- quantile(x, i, na.rm=TRUE) if ((breaks[1] %% 1) != 0) { breaks[1] <- breaks[1] - 0.000001 } if ((breaks[n] %% 1) != 0) { breaks[n] <- breaks[n] + 0.000001 } } else { # if (method=="eqint") { if (is.null(r)) { r <- c(min(x, na.rm=TRUE), max(x, na.rm=TRUE)) } if ((r[1] %% 1) != 0) { r[1] <- r[1] - 0.00001 } if ((r[2] %% 1) != 0) { r[2] <- r[2] + 0.00001 } breaks <- seq(r[1] , r[2], length.out=n+1) } breaks } .get_nrnc <- function(nr, nc, nl) { if (missing(nc)) { nc <- ceiling(sqrt(nl)) } else { nc <- max(1, min(nl, round(nc))) } if (missing(nr)) { nr <- ceiling(nl / nc) } else { nr <- max(1, min(nl, round(nr))) nc <- ceiling(nl / nr) } c(nr, nc) } .plot.axes <- function(x) { if (is.null(x$axs$cex.axis)) { x$axs$cex.axis = 0.7 } if (is.null(x$axs$mgp)) { x$axs$mgp = c(2, .25, 0) } if (is.null(x$axs$tcl)) { x$axs$tcl <- -0.25 } if (x$draw_grid) { x$axs$tck <- 1 x$axs$mgp = c(2, .15, 0) } if (!is.null(x$axs$sides)) { if (x$axs$sides[1] > 0) { usr <- graphics::par("usr") sides <- x$axs$sides x$axs$sides <- NULL sides <- round(unique(sides)) sides[sides > 1 & sides < 5] for (s in sides) { if (s %in% c(1,3)) { ur <- usr[2] - usr[1] at <- c(usr[1]-10*ur, usr[2]+10*ur) } else { ur <- usr[4] - usr[3] at <- c(usr[3]-10*ur, usr[4]+10*ur) } graphics::axis(s, at=at, labels=c("",""), lwd.ticks=0, cex.axis=x$axs$cex.axis, mgp=x$axis$mgp) x$axs$side <- s do.call(graphics::axis, x$axs) } x$axs$sides <- x$sides } } else { x$axs$side <- 1 do.call(graphics::axis, x$axs) x$axs$side <- 2 do.call(graphics::axis, x$axs) graphics::box() } x$axs$side <- NULL x } .get.leg.coords <- function(x) { if (is.null(x$leg$ext)) { ext <- unlist(x$ext) xmin <- x$ext[1] xmax <- x$ext[2] ymin <- x$ext[3] ymax <- x$ext[4] } else { p <- as.vector(x$leg$ext) xmin <- p[1] xmax <- p[2] ymin <- p[3] ymax <- p[4] #ymin <- max(ymin, ext["ymin"]) #ymax <- min(ymax, ext["ymax"]) } if (is.null(x$leg$shrink)) { leg.shrink <- c(0,0) } else { leg.shrink <- rep_len(x$leg$shrink,2) } if (!is.null(x$leg$main)) { n <- length(x$leg$main) leg.shrink[2] <- max(x$leg$shrink[2], (.05*n)) } if (isTRUE(x$leg$loc=="bottom")) { xd <- xmax - xmin xmin <- xmin + xd * leg.shrink[1] xmax <- xmax - xd * leg.shrink[2] yd <- ymax - ymin ymin <- ymin + yd * leg.shrink[1]/1.5 ymax <- ymax - yd * leg.shrink[2]/1.5 } else { yd <- ymax - ymin ymin <- ymin + yd * leg.shrink[1] ymax <- ymax - yd * leg.shrink[2] xd <- xmax - xmin xmin <- xmin + xd * leg.shrink[1]/1.5 xmax <- xmax - xd * leg.shrink[2]/1.5 } dx <- xmax - xmin dy <- ymax - ymin x$leg$ext <- data.frame(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, dx=dx, dy=dy) x } .line.usr <- function(line, side) { ## https://stackoverflow.com/questions/30765866/get-margin-line-locations-in-log-space/30835971#30835971 lh <- graphics::par("cin")[2] * graphics::par("cex") * graphics::par("lheight") x_off <- diff(graphics::grconvertX(c(0, lh), "inches", "npc")) y_off <- diff(graphics::grconvertY(c(0, lh), "inches", "npc")) if (side == 1) { graphics::grconvertY(-line * y_off, "npc", "user") } else if (side ==2) { graphics::grconvertX(-line * x_off, "npc", "user") } else if (side ==3) { graphics::grconvertY(1 + line * y_off, "npc", "user") } else { graphics::grconvertX(1 + line * x_off, "npc", "user") } } .get.leg.extent <- function(x) { usr <- graphics::par("usr") dxy <- graphics::par("cxy") * graphics::par("cex") loc <- x$leg$loc p <- NULL if (is.character(loc)) { if (loc == "right") { p <- c(usr[2]+dxy[1], usr[2]+2*dxy[1], usr[3], usr[4]) } else if (loc == "left") { s <- .line.usr(trunc(graphics::par("mar")[2]), 2) p <- c(s+4*dxy[1], s+5*dxy[1], usr[3], usr[4]) } else if (loc == "bottom") { s <- .line.usr(trunc(graphics::par("mar")[1]), 1) p <- c(usr[1], usr[2], s+2*dxy[2], s+3*dxy[2]) } else if (loc == "top") { p <- c(usr[1], usr[2], usr[4]+dxy[2], usr[4]+2*dxy[2]) } else { warn("plot", "invalid legend location:", loc) p <- c(usr[1], usr[2], usr[4]+dxy[2], usr[4]+2*dxy[2]) } } x$leg$ext <- p x$leg$user <- FALSE .get.leg.coords(x) } .leg.main <- function(x) { leg <- x$leg if (!is.null(leg$title)) { e <- leg$ext n <- length(leg$title) ymax <- e$ymax + 0.05 * e$dy for (i in 1:n) { if (x$leg$loc == "right") { text(x=e$xmax, y=ymax+(n-i)*0.05* e$dy, labels = leg$title[i], cex = leg$title.cex, xpd=TRUE) } else if (x$leg$loc == "left") { text(x=e$xmin, y=ymax+(n-i)*0.05* e$dy, labels = leg$title[i], cex = leg$title.cex, xpd=TRUE) } else { ymax <- e$ymax + e$dy text(x=(e$xmin+e$xmax)/2, y=ymax+(n-i)*0.05* e$dy, labels = leg$title[i], cex = leg$title.cex, xpd=TRUE) } } } x } .plot.cont.legend <- function(x, ...) { if (is.null(x$leg$ext)) { x <- .get.leg.extent(x) } else { x <- .get.leg.coords(x) } cex <- x$leg$cex if (is.null(cex)) cex <- 0.8 rotate <- isTRUE(x$leg$rotate) srt <- ifelse(rotate, 90, 0) cols <- rev(x$cols) nc <- length(cols) zlim <- x$range zz <- x$leg$at if (is.null(zz)) { if (is.null(x$levels)){ x$levels <- 5 } zz <- pretty(zlim, n =(x$levels+1)) zz <- zz[zz >= zlim[1] & zz <= zlim[2]] } zztxt <- x$leg$labels if (is.null(zztxt)) { zztxt <- formatC(zz, digits=x$leg$digits, format = "f") } e <- x$leg$ext if (x$leg$loc %in% c("left", "right")) { Y <- seq(e$ymin, e$ymax, length.out=nc+1) graphics::rect(e$xmin, Y[-(nc + 1)], e$xmax, Y[-1], col=rev(cols), border=NA, xpd=NA) ypos <- e$ymin + (zz - zlim[1])/(zlim[2] - zlim[1]) * e$dy if (x$leg$loc == "right") { graphics::segments(e$xmin, ypos, e$xmax+e$dx*0.25, ypos, xpd=NA) text(e$xmax, ypos, zztxt, pos=4, xpd=NA, cex=cex, ...) } else { graphics::segments(e$xmin-e$dx*0.25, ypos, e$xmax, ypos, xpd=NA) text(e$xmin, ypos, zztxt, pos=2, xpd=NA, cex=cex, ...) } } else { X <- seq(e$xmin, e$xmax, length.out=nc+1) graphics::rect(X[-(nc + 1)], e$ymin, X[-1], e$ymax, col=rev(cols), border=NA, xpd=NA) xpos <- e$xmin + (zz - zlim[1])/(zlim[2] - zlim[1]) * e$dx if (x$leg$loc == "bottom") { graphics::segments(xpos, e$ymin-e$dy*0.25, xpos, e$ymax, xpd=NA) text(xpos, e$ymin, zztxt, pos=1, xpd=NA, cex=cex) } else { graphics::segments(xpos, e$ymin, xpos, e$ymax+e$dy*0.25, xpd=NA) text(xpos, e$ymax+e$dy*0.25, zztxt, pos=3, xpd=NA, cex=cex) } } graphics::rect(e$xmin, e$ymin, e$xmax, e$ymax, border ="black", xpd=NA) x$leg.main <- .leg.main(x) x } .plot.class.legend <- function(x, y, legend, fill, xpd=TRUE, cex=0.8, geomtype="", lty=1, lwd=1, pch=1, angle=45, density=NULL, pt.cex = 1, pt.bg="black", pt.lwd=1, bty="n", border="black", seg.len=1, # catching merge, trace,...) { if (x == "top") { usr <- graphics::par("usr") x <- usr[c(2)] y <- usr[c(4)] } if (grepl("points", geomtype)) { leg <- legend(x, y, legend, col=fill, xpd=xpd, bty=bty, cex=cex, pch=pch, pt.cex=pt.cex, pt.bg=pt.bg, pt.lwd=pt.lwd, ...) } else if (geomtype == "lines") { leg <- legend(x, y, legend, col=fill, xpd=xpd, bty=bty, cex=cex, lty=lty, lwd=lwd, seg.len=seg.len, ...) } else { leg <- legend(x, y, legend, fill=fill, xpd=xpd, bty=bty, cex=cex, density=density*2, angle=angle, border=border, ...) } } terra/R/Agenerics.R0000644000175000017500000006413414201035747013760 0ustar nileshnilesh#if (!isGeneric("#")) { setGeneric("#", function(x, ...) standardGeneric("#")) } if (!isGeneric("query")) {setGeneric("query", function(x, ...) standardGeneric("query"))} if (!isGeneric("set.values")) {setGeneric("set.values", function(x, ...) standardGeneric("set.values"))} if (!isGeneric("set.ext")) {setGeneric("set.ext", function(x, ...) standardGeneric("set.ext"))} if (!isGeneric("set.names")) {setGeneric("set.names", function(x, ...) standardGeneric("set.names"))} if (!isGeneric("set.crs")) {setGeneric("set.crs", function(x, ...) standardGeneric("set.crs"))} if (!isGeneric("math")) { setGeneric("math", function(x, ...) standardGeneric("math")) } if (!isGeneric("all.equal")) { setGeneric("all.equal", function(target, current, ...) standardGeneric("all.equal")) } if (!isGeneric("impose")) { setGeneric("impose", function(x, ...) standardGeneric("impose")) } if (!isGeneric("density")) { setGeneric("density", function(x, ...) standardGeneric("density"))} if (!isGeneric("densify")) { setGeneric("densify", function(x, ...) standardGeneric("densify"))} if (!isGeneric("selectHighest")) {setGeneric("selectHighest", function(x, ...) standardGeneric("selectHighest"))} if (!isGeneric("focal3D")) { setGeneric("focal3D", function(x, ...) standardGeneric("focal3D")) } if (!isGeneric("focalReg")) { setGeneric("focalReg", function(x, ...) standardGeneric("focalReg")) } if (!isGeneric("focalCpp")) { setGeneric("focalCpp", function(x, ...) standardGeneric("focalCpp")) } if (!isGeneric("focalCor")) { setGeneric("focalCor", function(x, ...) standardGeneric("focalCor")) } if (!isGeneric("clearance")) {setGeneric("clearance", function(x, ...) standardGeneric("clearance"))} if (!isGeneric("width")) {setGeneric("width", function(x, ...) standardGeneric("width"))} if (!isGeneric("simplifyGeom")) {setGeneric("simplifyGeom", function(x, ...) standardGeneric("simplifyGeom"))} if (!isGeneric("mergeLines")) {setGeneric("mergeLines", function(x, ...) standardGeneric("mergeLines"))} if (!isGeneric("mergeTime")) {setGeneric("mergeTime", function(x, ...) standardGeneric("mergeTime"))} if (!isGeneric("fillTime")) {setGeneric("fillTime", function(x, ...) standardGeneric("fillTime"))} if (!isGeneric("makeNodes")) {setGeneric("makeNodes", function(x, ...) standardGeneric("makeNodes"))} if (!isGeneric("removeDupNodes")) {setGeneric("removeDupNodes", function(x, ...) standardGeneric("removeDupNodes"))} if (!isGeneric("snap")) {setGeneric("snap", function(x, ...) standardGeneric("snap"))} if (!isGeneric("weighted.mean")) {setGeneric("weighted.mean", function(x, w, ...) standardGeneric("weighted.mean"))} if (!isGeneric("split")) {setGeneric("split", function(x, f, drop = FALSE, ...) standardGeneric("split"))} if (!isGeneric("cellSize")) {setGeneric("cellSize", function(x, ...) standardGeneric("cellSize"))} if (!isGeneric("na.omit")) {setGeneric("na.omit", function(object, ...) standardGeneric("na.omit"))} if (!isGeneric("catalyze")) {setGeneric("catalyze", function(x, ...) standardGeneric("catalyze"))} if (!isGeneric("activeCat")) {setGeneric("activeCat", function(x, ...) standardGeneric("activeCat"))} if (!isGeneric("activeCat<-")) {setGeneric("activeCat<-", function(x, ..., value) standardGeneric("activeCat<-"))} if (!isGeneric("sharedPaths")) {setGeneric("sharedPaths", function(x, ...) standardGeneric("sharedPaths"))} if (!isGeneric("isTRUE")) {setGeneric("isTRUE", function(x) standardGeneric("isTRUE"))} if (!isGeneric("subst")) {setGeneric("subst", function(x, ...) standardGeneric("subst"))} if (!isGeneric("colorize")) {setGeneric("colorize", function(x, ...) standardGeneric("colorize"))} if (!isGeneric("RGB")) {setGeneric("RGB", function(x, ...) standardGeneric("RGB"))} if (!isGeneric("RGB<-")) {setGeneric("RGB<-", function(x, ..., value) standardGeneric("RGB<-"))} if (!isGeneric("autocor")) {setGeneric("autocor", function(x, ...) standardGeneric("autocor"))} if (!isGeneric("delauny")) {setGeneric("delauny", function(x, ...) standardGeneric("delauny"))} if (!isGeneric("voronoi")) {setGeneric("voronoi", function(x, ...) standardGeneric("voronoi"))} if (!isGeneric("convHull")) {setGeneric("convHull", function(x, ...) standardGeneric("convHull"))} if (!isGeneric("minRect")) {setGeneric("minRect", function(x, ...) standardGeneric("minRect"))} if (!isGeneric("is.related")) {setGeneric("is.related", function(x, y, ...) standardGeneric("is.related"))} if (!isGeneric("relate")) {setGeneric("relate", function(x, y, ...) standardGeneric("relate"))} if (!isGeneric("intersect")) {setGeneric("intersect", function(x, y) standardGeneric("intersect"))} if (!isGeneric("erase")) {setGeneric("erase", function(x, y, ...) standardGeneric("erase"))} if (!isGeneric("gaps")) {setGeneric("gaps", function(x, ...) standardGeneric("gaps"))} if (!isGeneric("is.int")) {setGeneric("is.int", function(x) standardGeneric("is.int"))} if (!isGeneric("as.int")) {setGeneric("as.int", function(x, ...) standardGeneric("as.int"))} if (!isGeneric("is.bool")) {setGeneric("is.bool", function(x) standardGeneric("is.bool"))} if (!isGeneric("as.bool")) {setGeneric("as.bool", function(x, ...) standardGeneric("as.bool"))} if (!isGeneric("nearby")) {setGeneric("nearby", function(x, ...) standardGeneric("nearby"))} if (!isGeneric("nearest")) {setGeneric("nearest", function(x, ...) standardGeneric("nearest"))} if (!isGeneric("cartogram")) {setGeneric("cartogram", function(x, ...) standardGeneric("cartogram"))} if (!isGeneric("dots")) {setGeneric("dots", function(x, ...) standardGeneric("dots"))} if (!isGeneric("crds")) {setGeneric("crds", function(x, ...) standardGeneric("crds"))} if (!isGeneric("symdif")) {setGeneric("symdif", function(x, y, ...) standardGeneric("symdif"))} if (!isGeneric("median")) {setGeneric("median", function(x, na.rm) standardGeneric("median"))} if (!isGeneric("polys")) {setGeneric("polys", function(x,...) standardGeneric("polys"))} if (!isGeneric("centroids")) {setGeneric("centroids", function(x, ...) standardGeneric("centroids"))} if (!isGeneric("coltab")) {setGeneric("coltab", function(x, ...) standardGeneric("coltab"))} if (!isGeneric("coltab<-")) { setGeneric("coltab<-", function(x, ..., value) standardGeneric("coltab<-")) } if (!isGeneric("deepcopy")) { setGeneric("deepcopy", function(x, ...) standardGeneric("deepcopy")) } if (!isGeneric("window")) {setGeneric("window", function(x, ...) standardGeneric("window"))} if (!isGeneric("window<-")) {setGeneric("window<-", function(x, ..., value) standardGeneric("window<-"))} if (!isGeneric("NAflag")) {setGeneric("NAflag", function(x, ...) standardGeneric("NAflag"))} if (!isGeneric("NAflag<-")) {setGeneric("NAflag<-", function(x, ..., value) standardGeneric("NAflag<-"))} if (!isGeneric("app")) { setGeneric("app", function(x, ...) standardGeneric("app"))} if (!isGeneric("lapp")) { setGeneric("lapp", function(x, ...) standardGeneric("lapp"))} if (!isGeneric("rapp")) { setGeneric("rapp", function(x, ...) standardGeneric("rapp"))} if (!isGeneric("tapp")) { setGeneric("tapp", function(x, ...) standardGeneric("tapp"))} if (!isGeneric("sapp")) { setGeneric("sapp", function(x, ...) standardGeneric("sapp"))} if (!isGeneric("add<-")) {setGeneric("add<-", function(x, value) standardGeneric("add<-"))} if (!isGeneric("align")) { setGeneric("align", function(x, y, ...) standardGeneric("align"))} if (!isGeneric("as.contour")) {setGeneric("as.contour", function(x,...) standardGeneric("as.contour"))} if (!isGeneric("as.lines")) {setGeneric("as.lines", function(x,...) standardGeneric("as.lines"))} if (!isGeneric("as.points")) {setGeneric("as.points", function(x,...) standardGeneric("as.points"))} if (!isGeneric("as.polygons")) {setGeneric("as.polygons", function(x,...) standardGeneric("as.polygons"))} if (!isGeneric("classify")) { setGeneric("classify", function(x, ...) standardGeneric("classify")) } if (!isGeneric("cells")) { setGeneric("cells", function(x, y, ...) standardGeneric("cells")) } if (!isGeneric("tighten")) {setGeneric("tighten", function(x, ...) standardGeneric("tighten"))} if (!isGeneric("compareGeom")) {setGeneric("compareGeom", function(x,y,...) standardGeneric("compareGeom"))} if (!isGeneric("crosstab")) { setGeneric("crosstab", function(x, y, ...) standardGeneric("crosstab")) } if (!isGeneric("describe")) { setGeneric("describe", function(x, ...) standardGeneric("describe"))} if (!isGeneric("depth")) {setGeneric("depth", function(x,...) standardGeneric("depth"))} if (!isGeneric("depth<-")) {setGeneric("depth<-", function(x, value) standardGeneric("depth<-"))} if (!isGeneric("draw")) {setGeneric("draw", function(x,...) standardGeneric("draw"))} if (!isGeneric("ext")) { setGeneric("ext", function(x, ...) standardGeneric("ext"))} if (!isGeneric("ext<-")) { setGeneric("ext<-", function(x, value) standardGeneric("ext<-")) } if (!isGeneric("fillHoles") ) { setGeneric("fillHoles", function(x, ...) standardGeneric("fillHoles")) } if (!isGeneric("geomtype")) {setGeneric("geomtype", function(x, ...) standardGeneric("geomtype"))} if (!isGeneric("datatype")) {setGeneric("datatype", function(x, ...) standardGeneric("datatype"))} if (!isGeneric("global")) {setGeneric("global", function(x, ...) standardGeneric("global"))} if (!isGeneric("makeValid")) {setGeneric("makeValid", function(x,...) standardGeneric("makeValid"))} if (!isGeneric("is.valid")) {setGeneric("is.valid", function(x,...) standardGeneric("is.valid"))} if (!isGeneric("is.points")) {setGeneric("is.points", function(x,...) standardGeneric("is.points"))} if (!isGeneric("is.lines")) {setGeneric("is.lines", function(x,...) standardGeneric("is.lines"))} if (!isGeneric("is.polygons")) {setGeneric("is.polygons", function(x,...) standardGeneric("is.polygons"))} if (!isGeneric("makeTiles")) {setGeneric("makeTiles", function(x,...) standardGeneric("makeTiles"))} if (!isGeneric("vrt")) {setGeneric("vrt", function(x,...) standardGeneric("vrt"))} if (!isGeneric("isTRUE")) { setGeneric("isTRUE", function(x) standardGeneric("isTRUE"))} if (!isGeneric("isFALSE")) { setGeneric("isFALSE", function(x) standardGeneric("isFALSE"))} if (!isGeneric("varnames")) {setGeneric("varnames", function(x,...) standardGeneric("varnames"))} if (!isGeneric("varnames<-")) {setGeneric("varnames<-", function(x, value) standardGeneric("varnames<-"))} if (!isGeneric("log")) {setGeneric("log", function(x,...) standardGeneric("log"))} if (!isGeneric("longnames")) {setGeneric("longnames", function(x,...) standardGeneric("longnames"))} if (!isGeneric("longnames<-")) {setGeneric("longnames<-", function(x, value) standardGeneric("longnames<-"))} if (!isGeneric("hasMinMax")) {setGeneric("hasMinMax", function(x) standardGeneric("hasMinMax"))} if (!isGeneric("minmax")) {setGeneric("minmax", function(x) standardGeneric("minmax"))} if (!isGeneric("nsrc")) { setGeneric("nsrc", function(x) standardGeneric("nsrc")) } if (!isGeneric("perim")) {setGeneric("perim", function(x, ...) standardGeneric("perim"))} if (!isGeneric("project")) {setGeneric("project", function(x,...) standardGeneric("project"))} if (!isGeneric("wrap")) {setGeneric("wrap", function(x, ...) standardGeneric("wrap"))} if (!isGeneric("cats")) { setGeneric("cats", function(x, ...) standardGeneric("cats")) } if (!isGeneric("setCats")) { setGeneric("setCats", function(x, ...) standardGeneric("setCats")) } if (!isGeneric("categories")) { setGeneric("categories", function(x, ...) standardGeneric("categories")) } if (!isGeneric("set.cats")) { setGeneric("set.cats", function(x, ...) standardGeneric("set.cats")) } if (!isGeneric("as.raster")) { setGeneric("as.raster", function(x, ...) standardGeneric("as.raster"))} if (!isGeneric("rast") ) { setGeneric("rast", function(x, ...) standardGeneric("rast")) } if (!isGeneric("rev") ) { setGeneric("rev", function(x) standardGeneric("rev")) } if (!isGeneric("sds") ) { setGeneric("sds", function(x, ...) standardGeneric("sds")) } if (!isGeneric("sprc") ) { setGeneric("sprc", function(x, ...) standardGeneric("sprc")) } if (!isGeneric("svc") ) { setGeneric("svc", function(x, ...) standardGeneric("svc")) } if (!isGeneric("sel")) {setGeneric("sel", function(x, ...) standardGeneric("sel"))} if (!isGeneric("segregate")) {setGeneric("segregate", function(x, ...) standardGeneric("segregate"))} if (!isGeneric("selectRange")) {setGeneric("selectRange", function(x, ...) standardGeneric("selectRange"))} if (!isGeneric("setValues")) {setGeneric("setValues", function(x, values, ...) standardGeneric("setValues"))} if (!isGeneric("expanse")) {setGeneric("expanse", function(x, ...) standardGeneric("expanse"))} if (!isGeneric("size")) {setGeneric("size", function(x, ...) standardGeneric("size"))} if (!isGeneric("inMemory")) {setGeneric("inMemory", function(x, ...) standardGeneric("inMemory"))} if (!isGeneric("sources")) {setGeneric("sources", function(x, ...) standardGeneric("sources"))} if (!isGeneric("spatSample")) { setGeneric("spatSample", function(x, ...) standardGeneric("spatSample"))} if (!isGeneric("terrain")) {setGeneric("terrain", function(x, ...) standardGeneric("terrain"))} if (!isGeneric("time")) {setGeneric("time", function(x,...) standardGeneric("time"))} if (!isGeneric("time<-")) {setGeneric("time<-", function(x, value) standardGeneric("time<-"))} if (!isGeneric("nlyr")) { setGeneric("nlyr", function(x) standardGeneric("nlyr")) } if (!isGeneric("nlyr<-")) { setGeneric("nlyr<-", function(x, ..., value) standardGeneric("nlyr<-")) } if (!isGeneric("linearUnits")) {setGeneric("linearUnits", function(x, ...) standardGeneric("linearUnits"))} if (!isGeneric("units")) {setGeneric("units", function(x) standardGeneric("units"))} if (!isGeneric("units<-")) {setGeneric("units<-", function(x,value) standardGeneric("units<-"))} if (!isGeneric("vect") ) { setGeneric("vect", function(x, ...) standardGeneric("vect")) } if (!isGeneric("writeCDF")) {setGeneric("writeCDF", function(x, filename, ...) standardGeneric("writeCDF"))} if (!isGeneric("writeVector")) {setGeneric("writeVector", function(x, filename, ...) standardGeneric("writeVector"))} ## shared with "raster" if (!isGeneric("%in%")) { setGeneric("%in%", function(x, table) standardGeneric("%in%")) } if (!isGeneric("adjacent")) {setGeneric("adjacent", function(x, ...) standardGeneric("adjacent"))} if (!isGeneric("animate")) { setGeneric("animate", function(x, ...) standardGeneric("animate")) } if (!isGeneric("approximate")) {setGeneric("approximate", function(x, ...) standardGeneric("approximate"))} if (!isGeneric("as.data.frame")) { setGeneric("as.data.frame", function(x, row.names = NULL, optional = FALSE, ...) standardGeneric("as.data.frame")) } if (!isGeneric("as.list")) { setGeneric("as.list", function(x, ...) standardGeneric("as.list"))} if (!isGeneric("as.factor")) {setGeneric("as.factor", function(x) standardGeneric("as.factor"))} if (!isGeneric("atan2")) { setGeneric("atan2", function(y, x) standardGeneric("atan2"))} if (!isGeneric("atan_2")) { setGeneric("atan_2", function(y, x, ...) standardGeneric("atan_2"))} if (!isGeneric("barplot")) {setGeneric("barplot", function(height,...) standardGeneric("barplot"))} #if (!isGeneric("bndbox")) {setGeneric("bndbox", function(obj) standardGeneric("bndbox"))} if (!isGeneric("boundaries")) { setGeneric("boundaries", function(x, ...) standardGeneric("boundaries"))} if (!isGeneric("boxplot")) { setGeneric("boxplot", function(x, ...) standardGeneric("boxplot"))} if (!isGeneric("buffer")) {setGeneric("buffer", function(x, ...) standardGeneric("buffer"))} if (!isGeneric("clamp")) { setGeneric("clamp", function(x, ...) standardGeneric("clamp")) } if (!isGeneric("click")) {setGeneric("click", function(x, ...)standardGeneric("click"))} if (!isGeneric("contour")) { setGeneric("contour", function(x,...) standardGeneric("contour"))} if (!isGeneric("cover")) {setGeneric("cover", function(x, y, ...) standardGeneric("cover"))} if (!isGeneric("crop")) { setGeneric("crop", function(x, y, ...) standardGeneric("crop")) } if (!isGeneric("crs")) { setGeneric("crs", function(x, ...) standardGeneric("crs")) } if (!isGeneric("crs<-")) { setGeneric("crs<-", function(x, ..., value) standardGeneric("crs<-")) } if (!isGeneric("density")) { setGeneric("density", function(x, ...) standardGeneric("density"))} if (!isGeneric("aggregate")) {setGeneric("aggregate", function(x, ...) standardGeneric("aggregate"))} if (!isGeneric("disagg")) {setGeneric("disagg", function(x, ...) standardGeneric("disagg"))} if (!isGeneric("gridDistance")) {setGeneric("gridDistance", function(x, ...)standardGeneric("gridDistance"))} if (!isGeneric("distance")) {setGeneric("distance", function(x, y, ...)standardGeneric("distance"))} if (!isGeneric("direction")) {setGeneric("direction", function(x, ...)standardGeneric("direction"))} if (!isGeneric("extract")) { setGeneric("extract", function(x, y, ...) standardGeneric("extract"))} if (!isGeneric("extend")) {setGeneric("extend", function(x, y, ...) standardGeneric("extend"))} if (!isGeneric("flip")) {setGeneric("flip", function(x, ...) standardGeneric("flip")) } if (!isGeneric("focal")) { setGeneric("focal", function(x, ...) standardGeneric("focal")) } if (!isGeneric("focalValues")) { setGeneric("focalValues", function(x, ...) standardGeneric("focalValues")) } if (!isGeneric("freq")) { setGeneric("freq", function(x, ...) standardGeneric("freq")) } if (!isGeneric("geom")) { setGeneric("geom", function(x,...) standardGeneric("geom"))} if (!isGeneric("hasValues")) {setGeneric("hasValues", function(x, ...) standardGeneric("hasValues")) } if (!isGeneric("head")) { setGeneric("head", function(x, ...) standardGeneric("head"))} if (!isGeneric("ifel")) {setGeneric("ifel", function(test, ...) standardGeneric("ifel"))} if (!isGeneric("image")) {setGeneric("image", function(x, ...)standardGeneric("image"))} if (!isGeneric("init")) {setGeneric("init", function(x, ...) standardGeneric("init"))} if (!isGeneric("inset")) {setGeneric("inset", function(x, ...) standardGeneric("inset"))} if (!isGeneric("inext")) {setGeneric("inext", function(x, ...) standardGeneric("inext"))} if (!isGeneric("interpolate")) { setGeneric("interpolate", function(object, ...) standardGeneric("interpolate"))} if (!isGeneric("is.factor")) {setGeneric("is.factor", function(x) standardGeneric("is.factor"))} if (!isGeneric("is.lonlat")) { setGeneric("is.lonlat", function(x, ...) standardGeneric("is.lonlat"))} if (!isGeneric("mask")) { setGeneric("mask", function(x, mask, ...) standardGeneric("mask")) } if (!isGeneric("match")) { setGeneric("match", function(x, table, nomatch=NA_integer_, incomparables=NULL) standardGeneric("match"))} if (!isGeneric("modal")) {setGeneric("modal", function(x, ...) standardGeneric("modal"))} if (!isGeneric("mosaic")) {setGeneric("mosaic", function(x, y, ...) standardGeneric("mosaic"))} if (!isGeneric("ncell")) { setGeneric("ncell", function(x) standardGeneric("ncell")) } if (!isGeneric("nrow")) { setGeneric("nrow", function(x) standardGeneric("nrow")) } if (!isGeneric("ncol")) { setGeneric("nrow", function(x) standardGeneric("nrow")) } if (!isGeneric("ncol<-")) { setGeneric("ncol<-", function(x, ..., value) standardGeneric("ncol<-")) } if (!isGeneric("nrow<-")) { setGeneric("nrow<-", function(x, ..., value) standardGeneric("nrow<-")) } if (!isGeneric("origin")) { setGeneric("origin", function(x, ...) standardGeneric("origin")) } if (!isGeneric("origin<-")) {setGeneric("origin<-", function(x, value) standardGeneric("origin<-"))} if (!isGeneric("pairs")) { setGeneric("pairs", function(x, ...) standardGeneric("pairs"))} if (!isGeneric("patches")) {setGeneric("patches", function(x, ...) standardGeneric("patches"))} if (!isGeneric("persp")) { setGeneric("persp", function(x,...) standardGeneric("persp")) } if (!isGeneric("plot")) { setGeneric("plot", function(x, y,...) standardGeneric("plot"))} if (!isGeneric("plotRGB")) { setGeneric("plotRGB", function(x, ...)standardGeneric("plotRGB"))} if (!isGeneric("predict")) {setGeneric("predict", function(object, ...) standardGeneric("predict"))} if (!isGeneric("quantile")) {setGeneric("quantile", function(x, ...)standardGeneric("quantile"))} if (!isGeneric("rasterize")) {setGeneric("rasterize", function(x, y, ...) standardGeneric("rasterize"))} if (!isGeneric("readStart")) {setGeneric("readStart", function(x, ...) standardGeneric("readStart"))} if (!isGeneric("readStop")) {setGeneric("readStop", function(x) standardGeneric("readStop"))} if (!isGeneric("res")) { setGeneric("res", function(x) standardGeneric("res")) } if (!isGeneric("res<-")) { setGeneric("res<-", function(x, value) standardGeneric("res<-")) } if (!isGeneric("rectify")) {setGeneric("rectify", function(x, ...) standardGeneric("rectify"))} if (!isGeneric("resample")) { setGeneric("resample", function(x, y, ...) standardGeneric("resample"))} if (!isGeneric("spin")) {setGeneric("spin", function(x, ...) standardGeneric("spin"))} if (!isGeneric("rotate")) {setGeneric("rotate", function(x, ...) standardGeneric("rotate"))} if (!isGeneric("rescale")) {setGeneric("rescale", function(x, ...) standardGeneric("rescale"))} #if (!isGeneric("select")) {setGeneric("select", function(x, ...) standardGeneric("select"))} if (!isGeneric("setMinMax")) {setGeneric("setMinMax", function(x, ...) standardGeneric("setMinMax"))} if (!isGeneric("scale")) {setGeneric("scale", function(x, center=TRUE, scale=TRUE) standardGeneric("scale"))} if (!isGeneric("shift")) {setGeneric("shift", function(x, ...) standardGeneric("shift"))} if (!isGeneric("stdev")) { setGeneric("stdev", function(x, ...) standardGeneric("stdev")) } if (!isGeneric("subset")) {setGeneric("subset", function(x, ...) standardGeneric("subset")) } if (!isGeneric("summary")) {setGeneric("summary", function(object, ...) standardGeneric("summary")) } if (!isGeneric("t")) { setGeneric("t", function(x) standardGeneric("t"))} if (!isGeneric("tail")) { setGeneric("tail", function(x, ...) standardGeneric("tail"))} if (!isGeneric("text")) { setGeneric("text", function(x, ...) standardGeneric("text")) } if (!isGeneric("trans")) { setGeneric("trans", function(x, ...) standardGeneric("trans"))} if (!isGeneric("trim")) { setGeneric("trim", function(x, ...) standardGeneric("trim")) } if (!isGeneric("xres")) { setGeneric("xres", function(x) standardGeneric("xres")) } if (!isGeneric("yres")) { setGeneric("yres", function(x) standardGeneric("yres")) } if (!isGeneric("zonal")) {setGeneric("zonal", function(x, z, ...) standardGeneric("zonal"))} if (!isGeneric("yFromRow")) { setGeneric("yFromRow", function(object, row) standardGeneric("yFromRow")) } if (!isGeneric("xFromCol")) { setGeneric("xFromCol", function(object, col) standardGeneric("xFromCol")) } if (!isGeneric("colFromX")) { setGeneric("colFromX", function(object, x) standardGeneric("colFromX")) } if (!isGeneric("rowFromY")) { setGeneric("rowFromY", function(object, y) standardGeneric("rowFromY")) } if (!isGeneric("cellFromXY")) { setGeneric("cellFromXY", function(object, xy) standardGeneric("cellFromXY")) } if (!isGeneric("cellFromRowCol")) { setGeneric("cellFromRowCol", function(object, row, col, ...) standardGeneric("cellFromRowCol")) } if (!isGeneric("cellFromRowColCombine")) { setGeneric("cellFromRowColCombine", function(object, row, col, ...) standardGeneric("cellFromRowColCombine")) } if (!isGeneric("xyFromCell")) { setGeneric("xyFromCell", function(object, cell, ...) standardGeneric("xyFromCell")) } if (!isGeneric("yFromCell")) { setGeneric("yFromCell", function(object, cell) standardGeneric("yFromCell")) } if (!isGeneric("xFromCell")) { setGeneric("xFromCell", function(object, cell) standardGeneric("xFromCell")) } if (!isGeneric("rowColFromCell")) { setGeneric("rowColFromCell", function(object, cell) standardGeneric("rowColFromCell")) } if (!isGeneric("rowFromCell")) { setGeneric("rowFromCell", function(object, cell) standardGeneric("rowFromCell")) } if (!isGeneric("colFromCell")) { setGeneric("colFromCell", function(object, cell) standardGeneric("colFromCell")) } if (!isGeneric("readStart")) { setGeneric("readStart", function(x, ...) standardGeneric("readStart")) } if (!isGeneric("readValues")) { setGeneric("readValues", function(x, ...) standardGeneric("readValues")) } if (!isGeneric("readStop")) { setGeneric("readStop", function(x, ...) standardGeneric("readStop")) } if (!isGeneric("setMinMax")) {setGeneric("setMinMax", function(x, ...) standardGeneric("setMinMax")) } if (!isGeneric("stretch")) {setGeneric("stretch", function(x, ...) standardGeneric("stretch")) } if (!isGeneric("union")) {setGeneric("union", function(x, y)standardGeneric("union"))} if (!isGeneric("unique")) { setGeneric("unique", function(x, incomparables=FALSE, ...) standardGeneric("unique")) } if (!isGeneric("values")) { setGeneric("values", function(x, ...) standardGeneric("values")) } if (!isGeneric("values<-")) { setGeneric("values<-", function(x, value) standardGeneric("values<-"))} if (!isGeneric("which.max")) {setGeneric("which.max", function(x) standardGeneric("which.max"))} if (!isGeneric("which.min")) {setGeneric("which.min", function(x) standardGeneric("which.min"))} if (!isGeneric("which.lyr")) {setGeneric("which.lyr", function(x) standardGeneric("which.lyr"))} if (!isGeneric("writeStart")) { setGeneric("writeStart", function(x, filename, ...) standardGeneric("writeStart")) } if (!isGeneric("writeStop")) { setGeneric("writeStop", function(x, ...) standardGeneric("writeStop")) } if (!isGeneric("writeValues")) { setGeneric("writeValues", function(x, v, ...) standardGeneric("writeValues")) } if (!isGeneric("writeRaster")) {setGeneric("writeRaster", function(x, filename, ...) standardGeneric("writeRaster"))} if (!isGeneric("xmin")) {setGeneric("xmin", function(x) standardGeneric("xmin"))} if (!isGeneric("xmax")) {setGeneric("xmax", function(x) standardGeneric("xmax"))} if (!isGeneric("ymin")) {setGeneric("ymin", function(x) standardGeneric("ymin"))} if (!isGeneric("ymax")) {setGeneric("ymax", function(x) standardGeneric("ymax"))} if (!isGeneric("xmin<-")) { setGeneric("xmin<-", function(x, ..., value) standardGeneric("xmin<-"))} if (!isGeneric("xmax<-")) { setGeneric("xmax<-", function(x, ..., value) standardGeneric("xmax<-"))} if (!isGeneric("ymin<-")) { setGeneric("ymin<-", function(x, ..., value) standardGeneric("ymin<-"))} if (!isGeneric("ymax<-")) { setGeneric("ymax<-", function(x, ..., value) standardGeneric("ymax<-"))} if (!isGeneric("zoom")) {setGeneric("zoom", function(x, ...)standardGeneric("zoom"))} terra/R/expand.R0000644000175000017500000000220614201035747013327 0ustar nileshnilesh setMethod("extend", signature(x="SpatExtent"), function(x, y) { if (length(y) == 1) { y <- rep(y, 4) } else if (length(y) == 2) { y <- rep(y, each=2) } else if (! length(y) == 4 ) { error("extend", 'argument "y" should be a vector of 1, 2, or 4 elements') } e <- as.vector(x) e[1] <- e[1] - y[1] e[2] <- e[2] + y[2] e[3] <- e[3] - y[3] e[4] <- e[4] + y[4] ext(e) } ) setMethod("extend", signature(x="SpatRaster"), function(x, y, snap="near", filename="", overwrite=FALSE, ...) { if (!inherits(y, "SpatExtent")) { if (is.vector(y)) { if (length(y) <= 2) { y <- round(y) stopifnot(all(y >= 0)) adj <- rev(y) * res(x) y <- as.vector(ext(x)) y[1] <- y[1] - adj[1] y[2] <- y[2] + adj[1] y[3] <- y[3] - adj[2] y[4] <- y[4] + adj[2] y <- ext(y) } } else { test <- try ( y <- ext(y), silent=TRUE ) if (class(test) == "try-error") { error("extend", "cannot get a SpatExtent object from argument y") } } } opt <- spatOptions(filename, overwrite, ...) x@ptr <- x@ptr$expand(y@ptr, snap[1], opt) messages(x, "extend") } ) terra/R/gridDistance.R0000644000175000017500000001703214201035747014453 0ustar nileshnilesh# Author: Jacob van Etten # email jacobvanetten@yahoo.com # Date : May 2010 # Version 1.1 # Licence GPL v3 # RH: updated for igraph (from igraph0) # sept 23, 2012 # RH: adapted from raster to terra # Jan 11, 2022 .calcDist <- function(r, origin=NULL, omit=NULL, filename, ...) { x <- rast(r) lonlat <- isTRUE(is.lonlat(x)) chunkSize <- ncell(x) ftC <- values(r, mat=FALSE) if (is.null(origin)) { oC <- which(!is.na(ftC)) } else { oC <- which(ftC %in% origin) } if (length(oC) == 0) { error("gridDistance", "no cells to compute distance to") } else if (length(oC) == ncell(x)) { return( init(x, 0, filename=filename, ...)) } ftC <- which(!(ftC %in% omit)) adj <- adjacent(x, ftC, directions=8, pairs=TRUE) if (!is.null(ftC)) { adj <- adj[adj[,2] %in% ftC, ,drop=FALSE] } startNode <- max(adj)+1 #extra node to serve as origin adjP <- rbind(adj, cbind(rep(startNode, times=length(oC)), oC)) distGraph <- igraph::graph.edgelist(adjP, directed=TRUE) perCell <- rep(0, times=length(oC)) if (lonlat) { distance <- distance(xyFromCell(x,adj[,1]), xyFromCell(x,adj[,2]), lonlat=TRUE, pairwise=TRUE) igraph::E(distGraph)$weight <- c(distance, perCell) } else { sameRow <- which(rowFromCell(x, adj[,1]) == rowFromCell(x, adj[,2])) sameCol <- which(colFromCell(x, adj[,1]) == colFromCell(x, adj[,2])) igraph::E(distGraph)$weight <- sqrt(xres(x)^2 + yres(x)^2) igraph::E(distGraph)$weight[sameRow] <- xres(x) igraph::E(distGraph)$weight[sameCol] <- yres(x) igraph::E(distGraph)$weight[(length(adj[,1])+1):(length(adj[,1])+length(oC))] <- perCell } shortestPaths <- igraph::shortest.paths(distGraph, startNode) if (length(shortestPaths) < chunkSize) { #add Inf values where shortest.paths() leaves off before completing all nodes shortestPaths <- c(shortestPaths, rep(Inf, times=chunkSize-length(shortestPaths))) } shortestPaths <- shortestPaths[-(length(shortestPaths))] #chop startNode off x <- setValues(x, shortestPaths) classify(x, cbind(Inf, NA), filename, ...) } .calcDistChunk <- function(x, chunkSize, ftC, oC, perCell=0, startCell=0, lonlat) { if (length(oC) > 0) { #adj <- adjacency(x, fromCells=ftC, toCells=ftC, directions=8) adj <- adjacent(x, ftC, directions=8, pairs=TRUE) if (!is.null(ftC)) { adj <- adj[adj[,2] %in% ftC, ,drop=FALSE] } startNode <- max(adj)+1 #extra node to serve as origin adjP <- rbind(adj, cbind(rep(startNode, times=length(oC)), oC)) distGraph <- igraph::graph.edgelist(adjP, directed=TRUE) if (length(perCell) == 1) { if (perCell == 0) { perCell <- rep(0, times=length(oC)) } } if (lonlat) { distance <- distance(xyFromCell(x,adj[,1]+startCell), xyFromCell(x,adj[,2]+startCell), lonlat=TRUE, pairwise=TRUE) igraph::E(distGraph)$weight <- c(distance, perCell) } else { sameRow <- which(rowFromCell(x, adj[,1]) == rowFromCell(x, adj[,2])) sameCol <- which(colFromCell(x, adj[,1]) == colFromCell(x, adj[,2])) igraph::E(distGraph)$weight <- sqrt(xres(x)^2 + yres(x)^2) igraph::E(distGraph)$weight[sameRow] <- xres(x) igraph::E(distGraph)$weight[sameCol] <- yres(x) igraph::E(distGraph)$weight[(length(adj[,1])+1):(length(adj[,1])+length(oC))] <- perCell } shortestPaths <- igraph::shortest.paths(distGraph, startNode) shortestPaths <- shortestPaths[-(length(shortestPaths))] #chop startNode off if (length(shortestPaths) < chunkSize) { #add Inf values where shortest.paths() leaves off before completing all nodes shortestPaths <- c(shortestPaths, rep(Inf, times=chunkSize-length(shortestPaths))) } } else { shortestPaths <- rep(Inf, times=chunkSize) } return(shortestPaths) } setMethod("gridDistance", signature(x="SpatRaster"), function(x, origin=NULL, omit=NULL, chunk=FALSE, filename="", overwrite=FALSE, ...) { if (! hasValues(x) ) { error("gridDistance", "SpatRaster has no cells values") } if (file.exists(filename) && (!isTRUE(overwrite))) { error("gridDistance", "file exists. Use 'overwrite=TRUE' if you want to overwrite it") } if( !requireNamespace("igraph")) { stop("the igraph package needs to be installed to use this function") } if (nlyr(x) > 1) { r <- list() for (i in 1:nlyr(x)) { r[[i]] <- gridDistance(x[[i]], origin=origin, omit=omit, chunk=chunk, filename="", ...) } r <- rast(r) if (filename != "") { r <- writeRaster(r, filename, overwrite, ...) } return(r) } if (!chunk) { x <- try(.calcDist(x, origin, omit, filename, ...)) if (inherits(x, "try-error")) { error("gridDistance", "gridDistance failed. Perhaps the raster is too large (set 'chunk=TRUE')?") } messages(x) } else { #going up lonlat <- isTRUE(is.lonlat(x)) r1 <- rast(x) b <- writeStart(r1, "") readStart(x) for (i in b$n:1) { chunk <- readValues(x, row=b$row[i], nrows=b$nrows[i]) startCell <- (b$row[i]-1) * ncol(x) chunkSize <- length(chunk) oC <- which(chunk %in% origin) ftC <- which(!(chunk %in% omit)) if (length(ftC) != 0) { if (i < b$n) { firstRowftC <- firstRowftC + chunkSize chunkDist <- .calcDistChunk(x, chunkSize=chunkSize + ncol(x), ftC=c(ftC, firstRowftC), oC=c(oC, firstRowftC), perCell=c(rep(0,times=length(oC)),firstRowDist), startCell=startCell, lonlat=lonlat)[1:chunkSize] } else { chunkDist <- .calcDistChunk(x, chunkSize=chunkSize, ftC=ftC, oC=oC, perCell=0, startCell=startCell, lonlat=lonlat) } } else { if (i < b$n) { firstRowftC <- firstRowftC + chunkSize } chunkDist <- rep(NA, b$nrows[i] * ncol(r1)) } firstRow <- chunk[1:ncol(x)] firstRowDist <- chunkDist[1:ncol(x)] firstRowftC <- which(!(firstRow %in% omit)) firstRowDist <- firstRowDist[firstRowftC] chunkDist[is.infinite(chunkDist)] <- NA writeValues(r1, chunkDist, b$row[i], b$nrows[i]) } writeStop(r1) readStart(r1) #going down out <- rast(x) b <- writeStart(out, filename=filename, overwrite=TRUE, ...) for (i in 1:b$n) { chunk <- readValues(x, row=b$row[i], nrows=b$nrows[i]) chunkSize <- length(chunk) startCell <- (b$row[i]-1) * ncol(x) oC <- which(chunk %in% origin) ftC <- which(!(chunk %in% omit)) if (length(ftC) != 0) { if (i > 1) { chunkDist <- readValues(r1, row=b$row[i], nrows=b$nrows[i]) chunkDist[is.na(chunkDist)] <- Inf chunkDist <- pmin(chunkDist, .calcDistChunk(x, chunkSize=chunkSize+ncol(x), ftC = c(lastRowftC, ftC+ncol(x)), oC = c(lastRowftC, oC+ncol(x)), perCell = c(lastRowDist, rep(0,times=length(oC))), startCell = startCell - ncol(x), lonlat=lonlat)[-(1:ncol(r1))]) } else { chunkDist <- readValues(r1, row=b$row[i], nrows=b$nrows[i]) chunkDist[is.na(chunkDist)] <- Inf chunkDist <- pmin(chunkDist, .calcDistChunk(x, chunkSize=chunkSize, ftC=ftC, oC=oC, perCell=0, startCell=startCell, lonlat=lonlat)) } } else { chunkDist <- rep(NA, b$nrows[i] * ncol(out)) } lastRow <- chunk[(length(chunk)-ncol(x)+1):length(chunk)] lastRowDist <- chunkDist[(length(chunkDist)-ncol(x)+1):length(chunkDist)] lastRowftC <- which(!(lastRow %in% omit)) lastRowDist <- lastRowDist[lastRowftC] chunkDist[is.infinite(chunkDist)] <- NA writeValues(out, chunkDist, b$row[i], b$nrows[i]) } readStop(x) writeStop(out) } } ) terra/R/read.R0000644000175000017500000000234614201035747012770 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : December 2017 # Version 1.0 # License GPL v3 readAll <- function(x) { ok <- x@ptr$readAll() x <- messages(x, "readAll") invisible(ok) } setMethod("readStart", signature(x="SpatRaster"), function(x) { success <- x@ptr$readStart() messages(x, "readStart") if (!success) error("readStart,SpatRaster", "cannot open file for reading") invisible(success) } ) setMethod("readStart", signature(x="SpatRasterDataset"), function(x) { success <- x@ptr$readStart() messages(x, "readStart") if (!success) error("readStart,SpatRasterDataset", "cannot open file for reading") invisible(success) } ) #setMethod("readStart", signature(x="SpatRasterDataset"), # function(x, ...) { # nsd <- length(x) # for (i in 1:nsd) { # y <- x[i] # success <- readStart(y) # x[i] <- y # } # messages(x, "readStart") # invisible(success) # } #) setMethod("readStop", signature(x="SpatRaster"), function(x) { success <- x@ptr$readStop() messages(x, "readStop") invisible(success) } ) setMethod("readStop", signature(x="SpatRasterDataset"), function(x) { success <- x@ptr$readStop() messages(x, "readStop") invisible(success) } ) terra/R/levels.R0000644000175000017500000002005214201035747013341 0ustar nileshnilesh setMethod("is.factor", signature(x="SpatRaster"), function(x) { x@ptr$hasCategories() } ) setMethod("as.factor", signature(x="SpatRaster"), function(x) { x <- round(x) u <- unique(x) levels(x) <- cbind(u, u) x } ) setMethod("levels", signature(x="SpatRaster"), function(x) { x <- x@ptr$getCategories() lapply(x, function(i) { d <- .getSpatDF(i$df) if (ncol(d) == 0) return("") d[,max(1, i$index+1)] }) } ) setMethod("levels<-", signature(x="SpatRaster"), function(x, value) { x@ptr <- x@ptr$deepcopy() if (is.null(value)) { x@ptr$removeCategories(0) return(messages(x, "levels<-")) } else if (inherits(value, "list")) { for (i in 1:length(value)) { set.cats(x, i, value[[i]]) } } else { set.cats(x, 1, value, 2) } x } ) setMethod ("set.cats" , "SpatRaster", function(x, layer=1, value, index) { layer <- layer[1] if (is.character(layer)) { i <- match(layer, names(x))[1] if (length(i) == 0) { error("setLevels", layer, " is not in names(x)") } layer <- i } else { stopifnot(layer > 0 && layer <= nlyr(x)) } if (missing(value)) { if (missing(index)) { return(x@ptr$getCatIndex(layer-1) + 1) } else { return(invisible(x@ptr$setCatIndex(layer-1, index))) } } if (missing(index)) { index <- 2 } if (is.null(value)) { x@ptr$removeCategories(layer-1) messages(x, "set.cats") return(invisible(TRUE)) } if (inherits(value, "list")) { value <- value[[1]] } setname <- FALSE if (!is.data.frame(value)) { if (is.vector(value) || is.factor(value)) { if ((length(value) == 1) && value[1] == "") { return(invisible("")) } value <- data.frame(value=0:(length(value)-1), category=value) } else { error("set.cats", "value should be a data.frame or a vector") } } else { setname <- TRUE if (ncol(value) == 1) { value <- data.frame(value=1:nrow(value), value) } else { value[,1] <- round(value[,1]) if (length(unique(value[,1])) != nrow(value)) { error("set.cats", "duplicate values (IDs) supplied") } } } index <- max(1, min(ncol(value), index)) # if (is.data.frame(value)) { if (setname) { nms <- names(x) nms[layer] <- colnames(value)[index] if (! x@ptr$setNames(nms, FALSE)) { error("names<-", "cannot set name") } } if (any(is.na(value[,1]))) { error("set.cats", "you cannot associate a category with NA") } value <- .makeSpatDF(value) ok <- x@ptr$setCategories(layer-1, value, index-1) # } else { # value <- as.character(value) # x@ptr$setLabels(layer-1, value) # } x <- messages(x, "set.cats") invisible(ok) } ) setMethod ("categories" , "SpatRaster", function(x, layer=1, value, index) { layer = layer[1] if (is.character(layer)) { i <- match(layer, names(x))[1] if (length(i) == 0) { error("setLevels", layer, " is not in names(x)") } layer <- i } else { stopifnot(layer > 0 && layer <= nlyr(x)) } x@ptr <- x@ptr$deepcopy() if (missing(value)) { if (missing(index)) { return(x@ptr$getCatIndex(layer-1) + 1) } else { return(invisible(x@ptr$setCatIndex(layer-1, index))) } } if (missing(index)) { index <- 2 } if (is.null(value)) { x@ptr$removeCategories(layer-1) return(messages(x, "set.cats")) } if (inherits(value, "list")) { value <- value[[1]] } setname <- FALSE if (!is.data.frame(value)) { if (is.vector(value) || is.factor(value)) { if ((length(value) == 1) && value[1] == "") { return(invisible("")) } value <- data.frame(value=0:(length(value)-1), category=value) } else { error("set.cats", "value should be a data.frame or a vector") } } else { setname <- TRUE if (ncol(value) == 1) { value <- data.frame(value=1:nrow(value), value) } else { value[,1] <- round(value[,1]) if (length(unique(value[,1])) != nrow(value)) { error("setCats", "duplicate ID values supplied") } } } # v <- data.frame(value=0:maxv) # value <- merge(v, value, by=1, all.x=TRUE) #} index <- max(1, min(ncol(value), index)) # if (is.data.frame(value)) { if (setname) { nms <- names(x) nms[layer] <- colnames(value)[index] if (! x@ptr$setNames(nms, FALSE)) { error("names<-", "cannot set name") } } if (any(is.na(value[,1]))) { error("categories", "you cannot associate a category with NA") } value <- .makeSpatDF(value) ok <- x@ptr$setCategories(layer-1, value, index-1) # } else { # value <- as.character(value) # x@ptr$setLabels(layer-1, value) # } messages(x, "categories") } ) setMethod ("activeCat" , "SpatRaster", function(x, layer=1) { layer = layer[1] if (is.character(layer)) { layer = which(layer == names(x))[1] if (is.na(layer)) { error("activeCat", "invalid layer name") } } if (!is.factor(x)[layer]) { return(NA) } x@ptr$getCatIndex(layer-1) } ) setMethod("activeCat<-" , "SpatRaster", function(x, layer=1, value) { if (missing(value)) { value <- layer[1] layer <- 1 } else { layer <- layer[1] } if ((layer < 1) | (layer > nlyr(x))) { error("activeCat", "invalid layer") } if (!is.factor(x)[layer]) { error("activeCat", "layer is not categorical") } if (is.character(value)) { g <- cats(x)[[layer]] value <- which(value == names(g))[1] - 1 if (is.na(value)) { error("activeCat", "invalid category name") } } if (!x@ptr$setCatIndex(layer-1, value)) { error("activeCat", "invalid category index") } x } ) setMethod("cats" , "SpatRaster", function(x, layer) { if (!missing(layer)) { x <- x[[layer]] } x <- x@ptr$getCategories() x <- lapply(x, function(i) { if (i$df$nrow == 0) return( NULL) .getSpatDF(i$df) }) x } ) active_cats <- function(x, layer) { ff <- is.factor(x) if (!any(ff)) { return (lapply(ff, function(i)NULL)) } cats <- x@ptr$getCategories() x <- lapply(1:length(cats), function(i) { if (cats[[1]]$df$nrow == 0) return(NULL) r <- .getSpatDF(cats[[i]]$df) a <- activeCat(x, i) r[, c(1, a+1)] }) if (!missing(layer)) { x[[layer]] } else { x } } setMethod ("as.numeric", "SpatRaster", function(x, index=NULL, filename="", ...) { stopifnot(nlyr(x) == 1) if (!is.factor(x)) return(x) g <- cats(x)[[1]] if (!is.null(index)) { if (!((index > 1) & (index <= ncol(g)))) { error("as.numeric", "invalid index") } } else { index <- set.cats(x, 1) } from <- g[,1] to <- g[,index] if (!is.numeric(to)) { to <- as.integer(as.factor(to)) } m <- cbind(from, to) m <- m[!is.na(m[,1]), ,drop=FALSE] classify(x, m, names=names(g)[index], filename, ...) } ) catLayer <- function(x, index, ...) { stopifnot(nlyr(x) == 1) if (!is.factor(x)) return(x) g <- cats(x)[[1]] if (!is.null(index)) { if (!((index > 1) & (index <= ncol(g)))) { error("as.numeric", "invalid index") } } else { index <- set.cats(x, 1) } from <- g[,1] toc <- g[,index] addFact <- FALSE if (!is.numeric(toc)) { addFact <- TRUE ton <- as.integer(as.factor(toc)) } else { ton <- toc } m <- cbind(from, ton) m <- m[!is.na(m[,1]), ,drop=FALSE] x <- classify(x, m, names=names(g)[index], ...) if (addFact) { fact <- unique(data.frame(ton, toc)) names(fact) <- c("ID", names(g)[index]) fact <- fact[order(fact[,1]), ] set.cats(x, 1, fact, 2) } x } setMethod("catalyze", "SpatRaster", function(x, filename="", ...) { g <- cats(x) out <- list() for (i in 1:nlyr(x)) { y <- x[[i]] gg <- g[[i]] if (nrow(gg) > 0) { for (j in 2:ncol(gg)) { z <- as.numeric(y, index=j) out <- c(out, z) } } else { out <- c(out, y) } } out <- rast(out) if (filename!="") { out <- writeRaster(out, filename, ...) } out } ) terra/R/show.R0000644000175000017500000003173714201035747013043 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : June 2017 # Version 1.0 # License GPL v3 printDF <- function(x, n=6, first=FALSE) { n <- min(nrow(x), max(n, 0)) old <- dim(x) if (old[2] == 0) { return() } if (old[1] > 0) { x <- x[1:n, ,drop=FALSE] } if (old[2] > 12) { x <- x[, 1:10] } d <- dim(x) cls <- sapply(x, class) cls <- gsub("integer", "int", cls) cls <- gsub("numeric", "num", cls) cls <- gsub("character", "chr", cls) cls <- paste0("<", cls, ">") cls <- data.frame(rbind(class=cls)) names(cls) <- NULL nms <- colnames(x) nc <- nchar(nms) mx <- max(15, 100/d[2]) i <- nc > (mx+2) nms[i] <- paste0(substr(nms[i], 1, (mx-1)), "~") if (d[1] > 0) { for (i in 1:ncol(x)) { if (is.character(x[[i]])) { x[[i]][is.na(x[[i]])] <- "NA" n <- nchar(x[[i]]) j <- n > (mx+2) x[[i]][j] <- paste0(substr(x[[i]][j], 1, (mx-1)), "~") } else if (is.numeric(x[[i]])) { x[[i]] <- formatC(x[[i]]) } } } x <- rbind(x[1,,drop=FALSE], x) x[1,] <- cls if (nrow(x) < d[1]) { x <- rbind(x, "...") } if (first) { x <- data.frame("", x, check.names=FALSE, stringsAsFactors=FALSE) colnames(x)[1] <- "names :" x[1,1] <- "type :" if (d[1] > 0) { x[2,1] <- "values :" } } if (old[2] > d[2]) { name <- paste0("(and ", old[2] - d[2], " more)") x[[name]] <- "" } print(x, row.names = FALSE) } setMethod ("show" , "Rcpp_SpatDataFrame", function(object) { cat("class :" , class(object), "\n") object <- .getSpatDF(object) d <- dim(object) cat("dimensions : ", d[1], ", ", d[2], " (nrow, ncol)\n", sep="" ) n <- 6 if (d[1] > 6) { cat("values (head)\n") } else { cat("values\n") } printDF(object) } ) setMethod ("show" , "Rcpp_SpatCategories", function(object) { show(object$df) } ) setMethod ("show" , "SpatExtent", function(object) { e <- as.vector(object) e <- paste(e, collapse=", ") cat("SpatExtent :", e, "(xmin, xmax, ymin, ymax)\n") } ) setMethod ("show" , "SpatVectorCollection", function(object) { cat(" class :", class(object), "\n") cat(" length :", length(object), "\n") for (i in 1:length(object)) { v <- object[i] if (i==1) { cat(" geometry : ", geomtype(v), " (", nrow(v) , ")\n", sep="") } else { cat(" ", geomtype(v), " (", nrow(v) , ")\n", sep="") } } } ) setMethod ("show" , "SpatVector", function(object) { e <- as.vector(ext(object)) d <- dim(object) cat(" class :", class(object), "\n") cat(" geometry :", geomtype(object), "\n") cat(" dimensions : ", d[1], ", ", d[2], " (geometries, attributes)\n", sep="" ) cat(" extent : ", e[1], ", ", e[2], ", ", e[3], ", ", e[4], " (xmin, xmax, ymin, ymax)\n", sep="") if (object@ptr$source != "") { if (object@ptr$layer != tools::file_path_sans_ext(basename(object@ptr$source))) { cat(" source : ", basename(object@ptr$source), " (", object@ptr$layer, ")\n", sep="") } else { cat(" source : ", basename(object@ptr$source), "\n", sep="") } } cat(" coord. ref. :", .name_or_proj4(object), "\n") if (d[2] > 0) { nr <- min(d[1], 3) dd <- as.data.frame(object[1:nr,]) printDF(dd, 3, TRUE) } } ) setMethod ("show" , "SpatVectorProxy", function(object) { e <- as.vector(ext(object)) d <- dim(object) cat(" class : SpatVectorProxy\n") cat(" geometry :", geomtype(object), "\n") cat(" dimensions : ", d[1], ", ", d[2], " (geometries, attributes)\n", sep="" ) cat(" extent : ", e[1], ", ", e[2], ", ", e[3], ", ", e[4], " (xmin, xmax, ymin, ymax)\n", sep="") if (object@ptr$v$layer != tools::file_path_sans_ext(basename(object@ptr$v$source))) { cat(" source : ", basename(object@ptr$v$source), " (", object@ptr$v$layer, ")\n", sep="") } else { cat(" source : ", basename(object@ptr$v$source), "\n", sep="") } cat(" coord. ref. :", .name_or_proj4(object), "\n") dd <- get.data.frame(object) printDF(dd, 0, TRUE) } ) setMethod ("show" , "SpatRaster", function(object) { cat("class :" , class(object), "\n") d <- dim(object) cat("dimensions : ", d[1], ", ", d[2], ", ", d[3], " (nrow, ncol, nlyr)\n", sep="" ) #cat ("ncell :" , ncell(object), "\n") xyres <- res(object) cat("resolution : " , xyres[1], ", ", xyres[2], " (x, y)\n", sep="") hw <- window(object) if (any(hw)) { w <- as.vector(ext(object)) if (all(hw)) { txt <- "window : " } else { txt <- "extent (win): " } cat(txt, w[1], ", ", w[2], ", ", w[3], ", ", w[4], " (xmin, xmax, ymin, ymax)\n", sep="") #e <- as.vector(object@ptr$source[[1]]$window$full_extent$vector) #cat("full extent : " , e[1], ", ", e[2], ", ", e[3], ", ", e[4], " (xmin, xmax, ymin, ymax)\n", sep="") } else { e <- as.vector(ext(object)) cat("extent : " , e[1], ", ", e[2], ", ", e[3], ", ", e[4], " (xmin, xmax, ymin, ymax)\n", sep="") } cat("coord. ref. :" , .name_or_proj4(object), "\n") if (hasValues(object)) { mnr <- 6 ln <- names(object) nl <- d[3] if (nl > mnr) { ln <- c(ln[1:mnr], "...") } lnmx <- 60 / min(mnr, length(ln)) b <- nchar(ln) > (lnmx+2) if (any(b)) { mid <- floor(lnmx/2) ln[b] <- paste(substr(ln[b], 1, mid), "~", substr(ln[b], nchar(ln[b])-mid+1, nchar(ln[b])), sep="") } nsr <- nsrc(object) m <- inMemory(object) f <- sources(object) hdf5 <- substr(f, 1, 5) == "HDF5:" f[!hdf5] <- basename(f[!hdf5]) if (any(hdf5)) { ff <- strsplit(f[hdf5], "://") ff <- sapply(ff, function(i) paste(basename(i), collapse="://")) ff <- gsub('\"', "", ff) f[hdf5] <- ff } #f <- gsub("\\", "/", f, fixed=TRUE) f <- gsub("\"", "", f) sources <- rep("memory", length(m)) sources[!m] <- f[!m] if (nsr > 1) { mxsrc <- 3 lbs <- .nlyrBySource(object) lbsprint <- paste0(" (", lbs, " layers)") lbsprint[lbs == 1] <- "" cat("sources :", sources[1], lbsprint[1], "\n") for (i in 2:(min(mxsrc, nsr))) { cat(" ", sources[i], lbsprint[i], "\n") } if (nsr > mxsrc) { cat(" ", "... and", nsr-mxsrc, "more source(s)\n") } } else { cat("source :", sources[1], "\n") } rgb <- RGB(object) if (!is.null(rgb)) { cat(paste("colors", toupper(object@ptr$rgbtype), " :"), paste(rgb, collapse=", "), "\n") } hasct <- object@ptr$hasColors() if (any(hasct)) { cat("color table :", paste(which(hasct), collapse=", "), "\n") } varnms <- varnames(object) fnms <- tools::file_path_sans_ext(f) if (any(fnms != varnms) && all(varnms != "")) { longnms <- longnames(object) i <- longnms != "" if (any(i)) { varnms[i] <- paste0(varnms[i], " (", longnms[i], ")") } if (nsr == 1) { cat("varname :", varnms[1], "\n") } else { cat("varnames :", varnms[1], "\n") for (i in 2:(min(nsr, 3))) { cat(" ", varnms[i], "\n") } } if (nsr > 3) { cat(" ...\n") } } uts <- units(object) hasunits <- !all(uts == "") if (nl > mnr) { uts <- c(uts[1:mnr], "...") } hMM <- hasMinMax(object) isB <- is.bool(object) if (any(hMM) || any(is.factor(object))) { #r <- minmax(object) r <- rbind(object@ptr$range_min, object@ptr$range_max) r[,!hMM] <- c(Inf, -Inf) minv <- format(r[1,]) maxv <- format(r[2,]) if (any(isB)) { minv[isB] <- ifelse(minv[isB]=="0", "FALSE", "TRUE") maxv[isB] <- ifelse(maxv[isB]=="0", "FALSE", "TRUE") } minv <- gsub("Inf", " ? ", minv) maxv <- gsub("-Inf", " ? ", maxv) minv[!hMM] <- gsub("NaN", " ? ", minv[!hMM]) maxv[!hMM] <- gsub("NaN", " ? ", maxv[!hMM]) minv[hw] <- paste0(">", minv[hw]) maxv[hw] <- paste0(maxv[hw],"<") if (nl > mnr) { minv <- c(minv[1:mnr], "...") maxv <- c(maxv[1:mnr], "...") } isf <- is.factor(object) if (any(isf)) { lv <- levels(object) for (i in 1:length(isf)) { if (i > mnr) break if (isf[i]) { cats <- stats::na.omit(lv[[i]]) cats <- sort(cats[cats != ""]) cats <- sort(cats[cats != "NA"]) if (length(cats) > 0) { minv[i] <- cats[1] maxv[i] <- cats[length(cats)] } } } } u8 <- Encoding(ln) == "UTF-8" wln <- nchar(ln) if (any(u8)) { # for Chinese: wln <- wln + u8 * wln w <- pmax(wln, nchar(minv), nchar(maxv), nchar(uts)) m <- rbind(paste0(rep(" ", max(wln)), collapse=""), minv, maxv) if (hasunits) m <- rbind(m, uts) # a loop because "width" is not recycled by format for (i in 1:ncol(m)) { m[,i] <- format(m[,i], width=w[i], justify="right") addsp <- w[i] - nchar(ln[i]) m[1,i] <- paste0(paste0(rep(" ", addsp), collapse=""), ln[i]) } } else { w <- pmax(wln, nchar(minv), nchar(maxv), nchar(uts)) m <- rbind(ln, minv, maxv) if (hasunits) m <- rbind(m, uts) # a loop because "width" is not recycled by format for (i in 1:ncol(m)) { m[,i] <- format(m[,i], width=w[i], justify="right") } } if (ncol(m) == 1) { if (is.factor(object)) { g <- cats(object)[[1]] if (ncol(g) > 2) { cat("categories :", paste(colnames(g)[-1], collapse=", "), "\n") } } cat("name :", paste(m[1,], collapse=", "), "\n") cat("min value :", paste(m[2,], collapse=", "), "\n") cat("max value :", paste(m[3,], collapse=", "), "\n") } else { cat("names :", paste(m[1,], collapse=", "), "\n") cat("min values :", paste(m[2,], collapse=", "), "\n") cat("max values :", paste(m[3,], collapse=", "), "\n") } if (hasunits) cat("unit :", paste(m[4,], collapse=", "), "\n") } else { w <- pmax(nchar(ln), nchar(uts)) m <- rbind(ln, uts) for (i in 1:ncol(m)) { m[,i] <- format(m[,i], width=w[i], justify="right") } if (ncol(m) == 1) { cat("name :", paste(m[1,], collapse=", "), "\n") } else { cat("names :", paste(m[1,], collapse=", "), "\n") } if (hasunits) cat("unit :", paste(m[2,], collapse=", "), "\n") } } if (object@ptr$hasTime) { rtim <- range(time(object)) utim <- unique(rtim) if (length(utim) > 1) { cat("time :", paste(rtim, collapse=" to "), "\n") } else { cat("time :", as.character(utim), "\n") } } # else { # cat("data sources:", "no data\n") # cat("names :", paste(ln, collapse=", "), "\n") # } } ) .sources <- function(x) { m <- inMemory(x) f <- sources(x) f <- gsub("\"", "", basename(f)) i <- grep(":", f) if (length(i) > 0) { for (j in i) { ff <- try(basename( strsplit(f[j], ':')[[1]][1]), silent=TRUE) if (!inherits(ff, "try-error")) { f[j] <- ff } } } sources <- rep("memory", length(m)) sources[!m] <- f[!m] unique(sources) } setMethod("show" , "SpatRasterDataset", function(object) { cat("class :" , class(object), "\n") ns <- length(object) cat("subdatasets :", ns, "\n") if (ns == 0) return() d <- dim(object) cat("dimensions :", paste(d, collapse=", "), "(nrow, ncol)\n") nss <- nlyr(object) if (length(nss) > 10) { nss = c(as.character(nss[1:9], "...")) } cat("nlyr :", paste(nss, collapse=", "), "\n") xyres <- res(object) cat("resolution : " , xyres[1], ", ", xyres[2], " (x, y)\n", sep="") e <- as.vector(ext(object)) cat("extent : " , e[1], ", ", e[2], ", ", e[3], ", ", e[4], " (xmin, xmax, ymin, ymax)\n", sep="") cat("coord. ref. :" , .name_or_proj4(object[1]), "\n") s <- unlist(lapply(1:ns, function(i) .sources(object[i]))) s <- unique(s) cat("source(s) :", paste(s, collapse=", "), "\n") ln <- names(object) if (any(ln != "")) { cat("names :", paste(ln, collapse=", "), "\n") } } ) setMethod("show" , "SpatRasterCollection", function(object) { cat("class :" , class(object), "\n") nr <- length(object) cat("length :", nr, "\n") } ) setMethod ("head" , "SpatVector", function(x, n=6L, ...) { nn <- min(n, nrow(x)) if (nn > 0) { x <- x[1:nn, ] } else { x <- x[0,] } as.data.frame(x) } ) setMethod ("tail" , "SpatVector", function(x, n=6L, ...) { nrx <- nrow(x) nn <- min(n, nrx) if (nn > 0) { start <- nrx - nn + 1 x <- x[start:nrx, ] } else { x <- x[0,] } x <- as.data.frame(x) if (nn > 0) { rownames(x) <- start:nrx } x } ) setMethod ("head" , "SpatRaster", function(x, n=6L, ...) { utils::head(x[1:n], n=n, ...) } ) setMethod ("tail" , "SpatRaster", function(x, n=6L, ...) { nc = ncell(x) utils::tail(x[(nc-n+1):nc], n=n, ...) } ) terra/R/approximate.R0000644000175000017500000000367514201035747014414 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : February 2012 # Version 1.0 # Licence GPL v3 setMethod("approximate", signature(x="SpatRaster"), function(x, method="linear", yleft, yright, rule=1, f=0, ties=mean, z=NULL, NArule=1, filename="", ...) { out <- rast(x, keeptime=TRUE) nl <- nlyr(out) if (nl < 2) { warning('cannot interpolate with a single layer') return(x) } if (is.null(z)) { xout <- time(x) if (any(is.na(xout))) { xout <- 1:nl } } else { if (length(z)!= nl) { error("approximate", "length of z does not match nlyr(x)") } xout <- z } ifelse((missing(yleft) & missing(yright)), ylr <- 0L, ifelse(missing(yleft), ylr <- 1L, ifelse(missing(yright), ylr <- 2L, ylr <- 3L))) nc <- ncol(out) readStart(x) on.exit(readStop(x)) b <- writeStart(out, filename, ...) for (i in 1:b$n) { v <- readValues(x, b$row[i], b$nrows[i], 1, nc, TRUE) s <- .rowSums(is.na(v), nrow(v), nl) if (isTRUE(NArule==1)) { j <- s == (nl-1) # one non-NA only if (length(j) > 0 ) { v[j, ] <- apply(v[j,,drop=FALSE ], 1, max, na.rm=TRUE) } } j <- (s < nl-1) # need at least two if (length(j) > 0 ) { if (ylr==0) { v[j,] <- t( apply(v[j,,drop=FALSE], 1, function(x) stats::approx(x=xout, y=x, xout=xout, method=method, rule=rule, f=f, ties=ties)$y ) ) } else if (ylr==1) { v[j,] <- t( apply(v[j,,drop=FALSE], 1, function(x) stats::approx(x=xout, y=x, xout=xout, method=method, yright=yright, rule=rule, f=f, ties=ties)$y ) ) } else if (ylr==2) { v[j,] <- t( apply(v[j,,drop=FALSE], 1, function(x) stats::approx(x=xout, y=x, xout=xout, method=method, yleft=yleft, rule=rule, f=f, ties=ties)$y ) ) } else { v[j,] <- t( apply(v[j,,drop=FALSE], 1, function(x) stats::approx(x=xout, y=x, xout=xout, method=method, yright=yright, yleft=yleft, rule=rule, f=f, ties=ties)$y ) ) } } writeValues(out, v, b$row[i], b$nrows[i]) } writeStop(out) } ) terra/R/sample.R0000644000175000017500000004035614201054343013332 0ustar nileshnilesh sampleWeights <- function(x, size, replace=FALSE, as.df=TRUE, as.points=FALSE, cells=FALSE, xy=FALSE, ext=NULL) { if (!is.null(ext)) { x <- crop(x, ext) } x <- classify(x, cbind(-Inf, 0, NA)) res <- as.data.frame(x, cells=cells, xy=(xy | as.points)) if (!replace) { if (size >= nrow(res)) { i <- 1:nrow(res) } else { i <- sample(nrow(res), size, prob=res[,ncol(res)], replace=replace) } } else { i <- sample(nrow(res), size, prob=res[,ncol(res)], replace=replace) } res <- res[i,] if (as.points) { res <- vect(res, c("x", "y"), crs=crs(x)) if (!xy) { res$x <- NULL res$y <- NULL } } else if (as.df) { res <- data.frame(res) } res } sampleStratified <- function(x, size, replace=FALSE, as.df=TRUE, as.points=FALSE, cells=TRUE, xy=FALSE, ext=NULL, warn=TRUE, exp=2, weights=NULL) { if ((!xy) && (!as.points)) cells <- TRUE f <- freq(x) exp <- max(1, exp) ss <- exp * size * nrow(f) lonlat <- is.lonlat(x, perhaps=TRUE, warn=FALSE) if (is.null(weights)) { if ((!lonlat) && (ss > (0.8 * ncell(x)))) { sr <- cbind(1:ncell(x), values(x)) colnames(sr) <- c("cell", names(x)) } else { sr <- spatSample(x, ss, "random", replace=replace, na.rm=TRUE, ext=ext, cells=TRUE, values=TRUE, warn=warn) } } else { if (!inherits(weights, "SpatRaster")) { error("spatSample", "weights must be a SpatRaster") } if (!compareGeom(x, weights)) { error("spatSample", "geometry of weights does not match the geometry of x") } sr <- vector("list", length = nrow(f)) for (i in 1:nrow(f)) { r <- x == f[i,2] r <- mask(weights, r, maskvalue=TRUE, inverse=TRUE) sr[[i]] <- sampleWeights(r, size, replace=replace, cells=TRUE, ext=ext)[,1] } sr <- unlist(sr) sr <- cbind(cell=sr, extract(x, sr)) } ys <- list() notfound <- NULL for (i in seq_len(nrow(f))) { y <- sr[sr[, 2] == f[i,2], ,drop=FALSE] if (nrow(y) == 0) { notfound <- c(notfound, i) } else { if (nrow(y) > size) { y <- y[sample(nrow(y), size), ,drop=FALSE] } ys[[i]] <- y } } res <- do.call(rbind, ys) colnames(res) <- c('cell', names(x)) ures <- unique(res[,2]) miss <- !(f[,"value"] %in% ures) if (any(miss) && warn) { miss <- which(miss) if (length(miss)== 1) { warn("sample", 'no samples for stratum: ', miss) } else if (length(miss) > 1) { warn("sample", 'no samples for strata: ', paste(miss, collapse=', ')) } } ta <- tapply(res[,1], res[,2], length) tanm <- names(ta)[which(ta < size)] if ((length(tanm) > 0) && warn) { if (length(tanm)== 1) { warn("sample", 'fewer samples than requested for stratum: ', tanm) } else if (length(tanm) > 1) { warn("sample", 'fewer samples than requested for strata: ', paste(tanm, collapse=', ')) } } if (xy) { pts <- xyFromCell(x, res[,1]) res <- cbind(res[,1,drop=FALSE], pts, res[,2,drop=FALSE]) } if (as.points) { if (!xy) { pts <- xyFromCell(x, res[,1]) } res <- vect(pts, crs=crs(x), atts=data.frame(res)) } else if (as.df) { res <- data.frame(res) } if (!cells) { res <- res[,-1,drop=FALSE] } res } .seed <- function() { sample.int(.Machine$integer.max, 1) } .sampleCells <- function(x, size, method, replace, na.rm=FALSE, ext=NULL) { r <- rast(x) lonlat <- is.lonlat(r, perhaps=TRUE, warn=TRUE) if (!is.null(ext)) { r <- crop(rast(r), ext) } if ( ((!replace) || (method == "regular")) && (size >= ncell(r)) ) { cells <- 1:ncell(r) } if (method == "random") { nsize <- size if (na.rm) { if (replace) { size <- size*5 } else { size <- min(ncell(r)*2, size*5) } } if (lonlat) { m <- ifelse(replace, 1.5, 1.25) n <- m * size y <- yFromRow(r, 1:nrow(r)) w <- abs(cos(pi*y/180)) rows <- sample.int(nrow(r), n, replace=TRUE, prob=w) cols <- sample.int(ncol(r), n, replace=TRUE) cells <- cellFromRowCol(r, rows, cols) if (!replace) { cells <- unique(cells) } } else { cells <- sample(ncell(r), size, replace=replace) } } else { # regular if (lonlat) { ratio <- 0.5 * ncol(r)/nrow(r) n <- sqrt(size) nx <- max(1, (round(n*ratio))) ny <- max(1, (round(n/ratio))) xi <- ncol(r) / nx yi <- nrow(r) / ny rows <- unique(round(seq(.5*yi, nrow(r), yi))) w <- cos(pi*yFromRow(r, rows)/180) w <- w * length(w)/sum(w) xi <- xi / w xi <- pmax(1,pmin(xi, ncol(r))) z <- list() #off <- stats::runif(1) for (i in 1:length(rows)) { z[[i]] <- cbind(rows[i], unique(round(seq(0.5*xi[i], ncol(r), xi[i])))) } z <- do.call(rbind, z) cells <- cellFromRowCol(r, z[,1], z[,2]) } else { f <- sqrt(size / ncell(r)) nr <- ceiling(nrow(r) * f) nc <- ceiling(ncol(r) * f); xstep <- ncol(r) / nc ystep <- nrow(r) / nr xsamp <- seq(0.5*xstep, ncol(r), xstep) ysamp <- seq(0.5*ystep, nrow(r), ystep) xy <- expand.grid(ysamp, xsamp) cells <- cellFromRowCol(r, xy[,1], xy[,2]) } } if (!is.null(ext)) { cells <- cellFromXY(x, xyFromCell(r, cells)) } if (na.rm) { v <- rowSums(is.na(x[cells])) == 0 cells <- cells[v] } if (method == "random") { if (length(cells) > nsize) { cells <- cells[1:nsize] } } return(cells) } set_factors <- function(x, ff, cts, asdf) { if (any(ff)) { x <- data.frame(x) for (i in which(ff)) { ct <- cts[[i]] m <- match(x[[i]], ct[,1]) if (!inherits(ct[[2]], "numeric")) { x[[i]] <- factor(ct[m,2], levels=unique(ct[[2]])) } else { x[[i]] <- ct[m,2] } } } else if (asdf) { x <- data.frame(x) } x } setMethod("spatSample", signature(x="SpatRaster"), function(x, size, method="random", replace=FALSE, na.rm=FALSE, as.raster=FALSE, as.df=TRUE, as.points=FALSE, values=TRUE, cells=FALSE, xy=FALSE, ext=NULL, warn=TRUE, weights=NULL) { size <- round(size) if (any(size < 1)) { error("spatSample", "sample size must be a positive integer") } if ((size > ncell(x)) & (!replace)) { size <- ncell(x) } method <- match.arg(tolower(method), c("random", "regular", "stratified", "weights")) if (method == "stratified") { if (as.raster) { error("as.raster is not valid for method='stratified'") } if (nlyr(x) > 1) { x <- x[[1]] warn("only the first layer of x is used") } if (!hasValues(x)) { error("x has no values") } return( sampleStratified(x, size, replace=replace, as.df=as.df, as.points=as.points, cells=cells, xy=xy, ext=ext, warn=warn, exp=5, weights=weights) ) } else if (!is.null(weights)) { error("spatSample", "argument weights is only used when method='stratified'") } if (method == "weights") { if (as.raster) { error("as.raster is not valid for method='weights'") } if (nlyr(x) > 1) { x <- x[[1]] warn("only the first layer of x is used") } if (!hasValues(x)) { error("x has no values") } out <- try(sampleWeights(x, size, replace=replace, as.df=as.df, as.points=as.points, cells=cells, xy=xy, ext=ext) ) if (inherits(out, "try-error")) { error("spatSample", "weighted sample failed. Perhaps the data set is too big") } return (out) } if (!as.raster) { ff <- is.factor(x) lv <- active_cats(x) } if (cells || xy || as.points) { size <- size[1] cnrs <- .sampleCells(x, size, method, replace, na.rm, ext) if (method == "random") { if (length(cnrs) < size) { warn("spatSample", "fewer cells returned than requested") } else if (length(cnrs) > size) { cnrs <- cnrs[1:size] } } out <- NULL if (cells) { out <- matrix(cnrs, ncol=1) colnames(out) <- "cell" } if (xy) { out <- cbind(out, xyFromCell(x, cnrs)) } if (values && hasValues(x)) { e <- extract(x, cnrs) e <- set_factors(e, ff, lv, as.df) if (is.null(out)) { out <- e } else { out <- cbind(out, e) } } if (as.points) { if (xy) { out <- vect(out, crs=crs(x)) } else { xy <- xyFromCell(x, cnrs) # xy is a matrix, no geom argument v <- vect(xy, crs=crs(x)) values(v) <- out return(v) } } return(out) } if (!hasValues(x) & !as.raster) { error("spatSample", "SpatRaster has no values") } method <- tolower(method) stopifnot(method %in% c("random", "regular")) if (!replace) size <- pmin(ncell(x), size) if (!is.null(ext)) x <- crop(x, ext) if (method == "regular") { if (as.raster) { if (length(size) > 1) { x@ptr <- x@ptr$sampleRowColRaster(size[1], size[2]) } else { x@ptr <- x@ptr$sampleRegularRaster(size) } x <- messages(x, "spatSample") return(x); } else { opt <- spatOptions() if (length(size) > 1) { v <- x@ptr$sampleRowColValues(size[1], size[2], opt) } else { v <- x@ptr$sampleRegularValues(size, opt) } x <- messages(x, "spatSample") if (length(v) > 0) { v <- do.call(cbind, v) colnames(v) <- names(x) } v <- set_factors(v, ff, lv, as.df) return(v) } } else { # random size <- size[1] if (as.raster) { x@ptr <- x@ptr$sampleRandomRaster(size, replace, .seed()) x <- messages(x, "spatSample") return(x); } else { #v <- x@ptr$sampleRandomValues(size, replace, seed) if (size > 0.75 * ncell(x)) { if (na.rm) { out <- stats::na.omit(values(x)) attr(x, "na.action") <- NULL if (nrow(out) < size) { warn("spatSample", "more non-NA cells requested than available") } else { out <- out[sample(nrow(out), size), ,drop=FALSE] } } else { out <- values(x) out <- out[sample(nrow(out), size, replace=replace), ,drop=FALSE] } out <- set_factors(out, ff, lv, as.df) return(out) } if (na.rm) { scells <- NULL ssize <- size*2 for (i in 1:10) { scells <- c(scells, .sampleCells(x, ssize, method, replace)) if ((i>1) && (!replace)) { scells <- unique(scells) } out <- stats::na.omit(x[scells]) if (nrow(out) >= size) { out <- out[1:size, ,drop=FALSE] attr(out, "na.action") <- NULL rownames(out) <- NULL break } } } else { scells <- .sampleCells(x, size, method, replace) out <- x[scells] } if (NROW(out) < size) { if (warn) warn("spatSample", "fewer values returned than requested") } else if (method == "random") { if (is.null(dim(out))) { out = out[1:size] } else { out = out[1:size, ,drop=FALSE] } } return(out) } } } ) setMethod("spatSample", signature(x="SpatExtent"), function(x, size, method="random", lonlat, as.points=FALSE) { if (missing(lonlat)) { error("spatSample", "provide a lonlat argument") } if (lonlat) { stopifnot(x$ymax <= 90 || x$ymin >= -90) } method <- match.arg(method, c("regular", "random")) size <- round(size) stopifnot(size > 0) if (method=="random") { s <- x@ptr$sampleRandom(size, lonlat, .seed()) } else { s <- x@ptr$sampleRegular(size, lonlat) } s <- do.call(cbind, s) colnames(s) <- c("x", "y") if (as.points) { s <- vect(s) } s } ) .grid_sample <- function(xy, n=1, r, chess="") { cell <- cellFromXY(r, xy) uc <- unique(stats::na.omit(cell)) chess <- trim(chess) if (chess != "") { chess <- match.arg(tolower(chess), c("white", "black")) nc <- ncol(r) if (nc %% 2 == 1) { if (chess=="white") { tf <- 1:ceiling(ncell(r)/2) * 2 - 1 } else { tf <- 1:ceiling((ncell(r)-1)/2) * 2 } } else { nr <- nrow(r) row1 <- 1:(ceiling(nr / 2)) * 2 - 1 row2 <- row1 + 1 row2 <- row2[row2 <= nr] if (chess=="white") { col1 <- 1:(ceiling(nc / 2)) * 2 - 1 col2 <- col1 + 1 col2 <- col2[col2 <= nc] } else { col1 <- 1:(ceiling(nc / 2)) * 2 col2 <- col1 - 1 col1 <- col1[col1 <= nc] } cells1 <- cellFromRowColCombine(r, row1, col1) cells2 <- cellFromRowColCombine(r, row2, col2) tf <- c(cells1, cells2) } uc <- uc[uc %in% tf] } cell <- cellFromXY(r, xy) cell <- cbind(1:nrow(xy), cell, stats::runif(nrow(xy))) cell <- stats::na.omit(cell) cell <- cell[order(cell[,3]), ] sel <- list() for (i in 1:length(uc)) { ss <- subset(cell, cell[,2] == uc[i]) sel[[i]] <- ss[1:min(n, nrow(ss)), 1] } unlist(sel) } #coordinates <- function(x) { # do.call(cbind, x@ptr$coordinates()) #} get_field_name <- function(x, nms, sender="") { x <- x[1] if (is.numeric(x)) { x <- round(x) if (x > 0 && x <= length(nms)) { x = nms[x] } else { error(sender, "invalid index. there are ", length(nms), " columns") } } else if (is.character(x)) { if (!(x %in% nms)) { error(sender, "invalid name") } } x } setMethod("spatSample", signature(x="SpatVector"), function(x, size, method="random", strata=NULL, chess="") { method = match.arg(tolower(method), c("regular", "random")) stopifnot(size > 0) gtype <- geomtype(x) if (gtype == "polygons") { if (!is.null(strata)) { if (length(strata) == 1) { if (is.character(strata)) { stopifnot(strata %in% names(x)) } else { stopifnot((strata > 0) && (strata < ncol(x))) } strata <- x[[strata, drop=TRUE]] } else if (length(strata) != length(x)) { stop("length of strata must be 1 or length(x)") } s <- stats::na.omit(unique(strata)) n <- length(size) if (n==1) { n <- rep_len(n, length(s)) } else if (length(s) != n) { stop("length of strata must be 1 or length(na.omit(unique(strata)))") } r <- lapply(s, function(s) { spatSample(x[strata == s, ], size, method, NULL, "") }) r <- do.call(rbind, r) return(r) } if (length(size) == 1) { x@ptr = x@ptr$sample(size, method[1], .seed()) } else { x@ptr = x@ptr$sampleGeom(size, method[1], .seed()) } return(messages(x)) } else if (grepl(gtype, "points")) { if (!is.null(strata)) { if (inherits(strata, "SpatRaster")) { xy <- crds(x) i <- .grid_sample(xy, size[1], rast(strata), chess) return(x[i,]) } else { error("spatSample", "not yet implemented for these strata") } } else { error("spatSample", "use `sample` to sample (point) geometries") } } else { error("spatSample", "not yet implemented for lines") } } ) #spatSample(disagg(as.points(v)), 1, "stratified", strata=r, chess="") # setMethod("spatSample", signature(x="SpatExtent"), # function(x, size, method="regular", lonlat, ...) { # if (missing(lonlat)) { # stop("provide a lonlat argument") # } # method = match.arg(method, c("regular", "random")) # size <- round(size) # stopifnot(size > 0) # e <- as.vector(x) # if (method=="random") { # if (lonlat) { # d <- round((e[4] - e[3]) * 1000); # dx <- (e[4] - e[3]) / (2 * d) # r <- unique(seq(e[3], e[4], length.out=d)) # w <- abs(cos(pi*r/180)) # x <- sample.int(length(r), size, prob=w, replace=TRUE) # lat <- r[x] + stats::runif(size, -dx, dx) # lon <- stats::runif(size, min = e[1], max = e[2]) # vect(cbind(lon,lat), crs="+proj=lonlat +datum=WGS84") # } else { # x <- stats::runif(size, min = e[1], max = e[2]) # y <- stats::runif(size, min = e[3], max = e[4]) # vect(cbind(x, y)) # } # } else { # r <- range(x) # ratio <- 0.5 * r[1]/r[2] # n <- sqrt(size) # nx <- max(1, (round(n*ratio))) # ny <- max(1, (round(n/ratio))) # xi <- r[1] / nx # yi <- r[2] / ny # if (lonlat) { # lat <- seq(e[3]+0.5*yi, e[4], yi) # w <- cos(pi*lat/180) # w <- w * length(w)/sum(w) # xi <- xi / w # xi <- pmin(xi, 180) # z <- list() # #off <- stats::runif(1) # for (i in 1:length(lat)) { # z[[i]] <- cbind(seq(e[1]+0.5*xi[i], e[2], xi[i]), lat[i]) # } # z <- do.call(rbind, z) # vect(z, crs="+proj=lonlat +datum=WGS84") # } else { # x <- seq(e[1]+0.5*xi, e[2], xi) # y <- seq(e[3]+0.5*yi, e[4], yi) # vect(cbind(rep(x, length(y)), rep(y, each=length(x)))) # } # } # } # ) terra/R/crs.R0000644000175000017500000001210014201035747012631 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : January 2009 # Version 0.9 # License GPL v3 is.proj <- function(crs) { substr(crs, 1, 6) == "+proj=" } .check_proj4_datum <- function(crs) { crs <- trimws(tolower(crs)) if (!is.proj(crs)) return() x <- trimws(unlist(strsplit(crs, "\\+"))) d <- grep("datum=", x, value=TRUE) if (length(d) > 0) { d <- gsub("datum=", "", d) if (!(d %in% c("wgs84", "nad83", "nad27"))) { warn("crs<-", "Only the WGS84, NAD83 and NAD27 datums can be used with a PROJ.4 string. Use WKT2, authority:code, or +towgs84= instead") } } #d <- grep("towgs84=", x, value=TRUE) #if (length(d) > 0) { # warn("crs<-", "+towgs84 parameters in a PROJ4 string are ignored") #} } .proj4 <- function(x) { x@ptr$get_crs("proj4") } .name_or_proj4 <- function(x) { if (inherits(x, "SpatVectorProxy")) { v <- vect() v@ptr <- x@ptr$v x <- v } d <- .srs_describe(x@ptr$get_crs("wkt")) r <- x@ptr$get_crs("proj4") if (!(d$name %in% c(NA, "unknown", "unnamed"))) { if (substr(r, 1, 13) == "+proj=longlat") { r <- paste("lon/lat", d$name) } else { r <- d$name } if (!is.na(d$code)) { r <- paste0(r, " (", d$authority, ":", d$code, ")") } } r } .srs_describe <- function(srs) { info <- .SRSinfo(srs) names(info) <- c("name", "authority", "code", "area", "extent") d <- data.frame(t(info), stringsAsFactors=FALSE) d$area <- gsub("\\.$", "", d$area) d[d == ""] <- NA if (is.na(d$extent)) { d$extent <- list(c(NA, NA, NA, NA)) } else { d$extent <- list(as.numeric(unlist(strsplit(d$extent, ",")))) } d } .get_CRS <- function(x, proj=FALSE, describe=FALSE, parse=FALSE) { if (describe) { d <- .srs_describe(x@ptr$get_crs("wkt")) if (proj) { d$proj <- x@ptr$get_crs("proj4") } d } else if (proj) { x@ptr$get_crs("proj4") } else { r <- x@ptr$get_crs("wkt") if (parse) { unlist(strsplit(r, "\n")) } else { r } } } setMethod("crs", signature("SpatRaster"), function(x, proj=FALSE, describe=FALSE, parse=FALSE) { .get_CRS(x, proj=proj, describe=describe, parse=parse) } ) setMethod("crs", signature("SpatRasterDataset"), function(x, proj=FALSE, describe=FALSE, parse=FALSE) { if (length(x) > 0) { .get_CRS(x[[1]], proj=proj, describe=describe, parse=parse) } else { NULL } } ) .txtCRS <- function(x, warn=TRUE) { if (inherits(x, "SpatVector") | inherits(x, "SpatRaster")) { x <- crs(x) } if (is.null(x) || is.na(x)) { x <- "" } else if (inherits(x, "CRS")) { if (warn) warn("crs", "expected a character string, not a CRS object") y <- attr(x, "comment") if (is.null(y)) { y <- x@projargs if (is.na(y)) y <- "" } x <- y } else if (is.character(x)) { x <- x[1] } else { error("crs", "I do not know what to do with this argument (expected a character string)") } .check_proj4_datum(x) x } setMethod("crs<-", signature("SpatRaster", "ANY"), function(x, value) { value <- .txtCRS(value) x@ptr <- x@ptr$deepcopy() x@ptr$set_crs(value) messages(x, "crs<-") } ) setMethod("set.crs", signature("SpatRaster"), function(x, value) { value <- .txtCRS(value) x@ptr$set_crs(value) messages(x, "set_crs") } ) #setMethod("crs<-", signature("SpatRaster", "character"), # function(x, ..., value) { # x@ptr$set_crs(value[1]) # messages(x, "crs<-") # } #) setMethod("crs", signature("SpatVector"), function(x, proj=FALSE, describe=FALSE, parse=FALSE) { .get_CRS(x, proj=proj, describe=describe, parse=parse) } ) setMethod("crs", signature("SpatVectorProxy"), function(x, proj=FALSE, describe=FALSE, parse=FALSE) { v <- vect() v@ptr <- x@ptr$v .get_CRS(v, proj=proj, describe=describe, parse=parse) } ) setMethod("crs<-", signature("SpatVector", "ANY"), function(x, value) { value <- .txtCRS(value) x@ptr <- x@ptr$deepcopy() x@ptr$set_crs(value) messages(x, "crs<-") } ) setMethod("set.crs", signature("SpatVector"), function(x, value) { value <- .txtCRS(value) x@ptr$set_crs(value) messages(x, "set_crs") } ) setMethod("is.lonlat", signature("SpatRaster"), function(x, perhaps=FALSE, warn=TRUE, global=FALSE) { if (perhaps) { ok <- x@ptr$isLonLat() if (ok) { if (global) { return(x@ptr$isGlobalLonLat()) } else { return(ok) } } ok <- x@ptr$couldBeLonLat() if (ok) { if (global) { ok <- x@ptr$isGlobalLonLat() } } if (ok && warn) { warn("is.lonlat", "assuming lon/lat crs") } } else { ok <- x@ptr$isLonLat() if (ok && global) { ok <- x@ptr$isGlobalLonLat() } if ((!ok) && (crs(x) == "")) { ok <- NA } } ok } ) setMethod("is.lonlat", signature("SpatVector"), function(x, perhaps=FALSE, warn=TRUE) { if (perhaps) { ok <- x@ptr$couldBeLonLat() if (ok && warn) { if (crs(x) == "") warn("is.lonlat", "assuming lon/lat crs") } } else { ok <- x@ptr$isLonLat() if ((!ok) && (crs(x) == "")) { ok <- NA } } ok } ) terra/R/zoom.R0000644000175000017500000000225014201035747013033 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : September 2009 # Version 0.9 # License GPL v3 setMethod("zoom", signature(x="SpatRaster"), function(x, e=draw(), maxcell=100000, layer=1, new=FALSE, ...) { if (grDevices::dev.cur() == 1) { if (!is.null(RGB(x))) { plot(x, maxcell=maxcell, ...) } else { plot(x, layer, maxcell=maxcell, ...) } } if (is.function(e)) { # force to start with drawing before creating a new graphics device e <- e } else if (!inherits(e, "SpatExtent")) { e <- ext(e) } if (new) { grDevices::dev.new() } if (!is.null(RGB(x))) { x <- crop(x, e) } else { x <- crop(x[[layer]], e) } plot(x, maxcell=maxcell, ...) return(invisible(e)) } ) setMethod("zoom", signature(x="SpatVector"), function(x, e=draw(), new=FALSE, ...) { if (grDevices::dev.cur() == 1) { plot(x, ...) } if (is.function(e)) { e <- e } else if (!inherits(e, "SpatExtent")) { e <- ext(e) } if (new) { grDevices::dev.new() } e <- as.vector(e) plot(0, type="n", xlim=e[1:2], ylim=e[3:4], xlab="", ylab="") plot(x, add=TRUE, ...) return(invisible(e)) } ) terra/R/select.R0000644000175000017500000000146514201035747013335 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : December 2011 # Version 1.0 # License GPL v3 setMethod("sel", signature(x="SpatRaster"), function(x, ...) { e <- draw(...) int <- intersect(e, ext(x)) if (is.null(int)) { x <- NULL } else { x <- crop(x, e) } x } ) setMethod("sel", signature(x="SpatVector"), function(x, use="rec", draw=TRUE, col="cyan", ...) { use <- substr(tolower(use), 1, 3) use <- match.arg(use, c("rec", "pol")) if (use == "rec") { e <- draw() # e <- as.polygons(e) } else { e <- draw("pol") } i <- relate(x, e, "intersects") x <- x[as.vector(i), ] if (draw) { if (geomtype(x) == "points" || geomtype(x) == "multipoints") { points(x, col=col, ...) } else { lines(x, col=col, ...) } } x } ) terra/R/plot_raster.R0000644000175000017500000003500514202251722014403 0ustar nileshnilesh .as.raster.continuous <- function(out, x, type) { Z <- as.matrix(x, wide=TRUE) Z[is.nan(Z) | is.infinite(Z)] <- NA z <- stats::na.omit(round(as.vector(Z), 12)) n <- length(z) if (n == 0) { out$values = FALSE return(out) } uzi <- unique(z) if (type == "depends") { if (length(uzi) < 6) { return (.as.raster.classes(out, x)) } } else if (length(uzi) == 1) { return (.as.raster.classes(out, x)) } if (is.null(out$range)) { out$range <- range(z) } else { stopifnot(length(out$range) == 2) stopifnot(out$range[2] > out$range[1]) } breaks <- .get_breaks(Z, length(out$cols), "eqint", out$range) Z[] <- out$cols[as.integer(cut(Z, breaks, include.lowest=TRUE, right=FALSE))] out$r <- as.raster(Z) out$legend_type <- "continuous" if (is.null(out$levels)) { out$levels <- 5 } if (is.null(out$leg$digits)) { dif <- diff(out$range) if (dif == 0) { out$leg_digits = 0; } else { out$leg$digits <- max(0, -floor(log10(dif/10))) } } if (is.null(out$leg$loc)) out$leg$loc <- "right" out } .as.raster.classes <- function(out, x, ...) { Z <- as.matrix(x, wide=TRUE) Z[is.nan(Z) | is.infinite(Z)] <- NA if (all(is.na(Z))) { out$values = FALSE return(out) } fz <- as.factor(Z) levs <- levels(fz) if (!is.null(out$levels)) { if (is.null(out$leg$legend)) { out$leg$legend <- as.character(out$levels) } levs <- out$levels } else { out$levels <- as.numeric(levs) if (is.null(out$leg$legend)) { out$leg$legend <- levs } } stopifnot(length(out$leg$legend) == length(out$levels)) nlevs <- length(levs) cols <- out$cols ncols <- length(cols) if (nlevs < ncols) { i <- trunc((ncols / nlevs) * 1:nlevs) cols <- cols[i] } else { cols <- rep_len(cols, nlevs) } out$leg$fill <- cols Z[] <- cols[as.numeric(fz)] out$r <- as.raster(Z) out$legend_type <- "classes" if (is.null(out$leg$x)) { if (is.null(out$leg$ext)) { out$leg$x = "top" out$leg$y = NULL } else { if (length(out$leg$ext) == 4) { out$leg$x = out$leg$ext[1] out$leg$y = out$leg$ext[4] } else { out$leg$x = "top" out$leg$y = NULL } } } out } .as.raster.factor <- function(out, x, ...) { z <- round(values(x)) #z[z<1 | z>256] <- NA z[is.nan(z) | is.infinite(z)] <- NA if (all(is.na(z))) { out$values = FALSE return(out) } out$levels <- sort(stats::na.omit(unique(z))) ilevels <- match(out$levels, out$cats[[1]]) out$leg$legend <- unique(na.omit(out$cats[ilevels, 2])) if (!is.null(out$coltab)) { # perhaps merge(z, cats, colors) intead for clarity out$levels <- out$levels[!is.na(ilevels)] m <- na.omit(match(out$levels[ilevels], out$coltab[,1])) out$coltab <- out$coltab[m, ,drop=FALSE] out$cols <- grDevices::rgb(out$coltab[,2], out$coltab[,3], out$coltab[,4], out$coltab[,5], maxColorValue=255) i <- match(z, out$coltab[,1]) z <- out$cols[i] #i <- match(ilevels, out$coltab[,1]) #out$cols <- out$cols[i] } else { #levlab <- data.frame(id=out$levels, lab=out$cats[[2]][ilevels], stringsAsFactors=FALSE) levlab <- data.frame(id=out$levels, lab=out$cats[ilevels, 2], stringsAsFactors=FALSE) leglevs <- na.omit(unique(levlab[,2])) if (length(leglevs) == 0) { error("plot", "something is wrong with the categories") } nlevs <- length(leglevs) ncols <- length(out$cols) if (nlevs < ncols) { i <- trunc((ncols / nlevs) * 1:nlevs) out$cols <- out$cols[i] } else if (nlevs > ncols) { out$cols <- rep_len(out$cols, nlevs) } dd <- data.frame(lab=leglevs, out$cols) m <- merge(levlab, dd) z <- m$out.cols[match(z, m$id)] } out$leg$fill <- out$cols z <- matrix(z, nrow=nrow(x), ncol=ncol(x), byrow=TRUE) out$r <- as.raster(z) out$legend_type <- "classes" if (is.null(out$leg$x)) { if (is.null(out$leg$ext)) { out$leg$x = "top" out$leg$y = NULL } else { if (length(out$leg$ext) == 4) { out$leg$x = out$leg$ext[1] out$leg$y = out$leg$ext[4] } else { out$leg$x = "top" out$leg$y = NULL } } } if (isTRUE(out$legend_sort)) { ord <- order(out$leg$legend) out$leg$legend <- out$leg$legend[ord] out$leg$fill <- out$leg$fill[ord] } out } # to be merged with the vector variant. .generic.interval <- function(out, Z) { if (is.null(out$breaks)) { out$breaks <- 5 } if (length(out$breaks) == 1) { out$breaks <- .get_breaks(Z, out$breaks, out$breakby, out$range) } fz <- cut(Z, out$breaks, include.lowest=TRUE, right=FALSE) out$vcut = as.integer(fz) levs <- levels(fz) nlevs <- length(levs) cols <- out$cols ncols <- length(cols) if (nlevs < ncols) { i <- trunc((ncols / nlevs) * 1:nlevs) cols <- cols[i] } else { cols <- rep_len(cols, nlevs) } #out$cols <- cols out$leg$fill <- cols #out$leg$levels <- levels(fz) out$legend_type <- "classes" if (!is.null(out$leg$legend)) { stopifnot(length(out$leg$legend) == nlevs) } else { levs <- gsub("]", "", gsub(")", "", gsub("\\[", "", levs))) levs <- paste(levs, collapse=",") m <- matrix(as.numeric(unlist(strsplit(levs, ","))), ncol=2, byrow=TRUE) m <- apply(m, 1, function(i) paste(i, collapse=" - ")) out$leg$legend <- m } if (is.null(out$leg$x)) { # && is.null(out$leg$ext)) { out$leg$x <- "top" } out } .as.raster.interval <- function(out, x, ...) { Z <- as.matrix(x, wide=TRUE) Z[is.nan(Z) | is.infinite(Z)] <- NA out <- .generic.interval(out, Z) Z[] <- out$leg$fill[out$vcut] out$r <- as.raster(Z) out } # leg.shrink=c(0,0), leg.main=NULL, leg.main.cex = 1, leg.digits=NULL, leg.loc=NULL, leg.ext=NULL, leg.levels=NULL, leg.labels=NULL, leg.at=NULL, .as.raster.colortable <- function(out, x, ...) { z <- round(values(x)) #z[z<0 | z>255] <- NA z[is.nan(z) | is.infinite(z)] <- NA if (all(is.na(z))) { out$values = FALSE return(out) } out$cols <- grDevices::rgb(out$coltab[,2], out$coltab[,3], out$coltab[,4], out$coltab[,5], maxColorValue=255) i <- match(z, out$coltab[,1]) z <- out$cols[i] z <- matrix(z, nrow=nrow(x), ncol=ncol(x), byrow=TRUE) out$r <- as.raster(z) out } # legend # border="black", box.lwd = graphics::par("lwd"), box.lty = graphics::par("lty"), # box.col = graphics::par("fg"), bty = "o", bg = graphics::par("bg"), xjust = 0, # yjust = 1, x.intersp = 1, y.intersp = 1, adj = c(0, 0.5), text.width = NULL, # text.col = graphics::par("col"), text.font = NULL, ncol = 1, horiz = FALSE, title = NULL, # inset = 0, title.col = text.col, title.adj = 0.5, .plotit <- function(x, xlab="", ylab="", type = "n", yaxs="i", xaxs="i", asp=x$asp, axes=TRUE, new=NA, main="", line=0.5, cex.main=0.8, font.main=graphics::par()$font.main, col.main = graphics::par()$col.main, reset=FALSE, ...) { # if (x$add) axes = FALSE if ((!x$add) & (!x$legend_only)) { old.mar <- graphics::par()$mar if (!any(is.na(x$mar))) { graphics::par(mar=x$mar) } if (reset) on.exit(graphics::par(mar=old.mar)) plot(x$lim[1:2], x$lim[3:4], type=type, xlab=xlab, ylab=ylab, asp=asp, xaxs=xaxs, yaxs=yaxs, axes=!x$values, ...) graphics::title(main, line=line, cex.main=cex.main, font.main=font.main, col.main=col.main) } if (!x$values) { return(x) } if (!x$legend_only) { graphics::rasterImage(x$r, x$ext[1], x$ext[3], x$ext[2], x$ext[4], angle = 0, interpolate = x$interpolate) if (axes) x <- .plot.axes(x) } if (x$legend_draw) { if (x$legend_type == "continuous") { x <- do.call(.plot.cont.legend, list(x=x)) # } else if (x$legend_type == "classes") { } else { #y <- do.call(.plot.class.legend, x$leg) leg <- do.call(.plot.class.legend, x$leg) } } x } .prep.plot.data <- function(x, type, cols, mar=NULL, draw=FALSE, interpolate=FALSE, legend=TRUE, legend.only=FALSE, pax=list(), plg=list(), levels=NULL, add=FALSE, range=NULL, new=NA, breaks=NULL, breakby="eqint", coltab=NULL, cats=NULL, xlim=NULL, ylim=NULL, ext=NULL, colNA=NA, alpha=NULL, reset=FALSE, sort=TRUE, grid=FALSE, las=0, ...) { #mar=c(5.1, 4.1, 4.1, 7.1); legend=TRUE; axes=TRUE; pal=list(); pax=list(); maxcell=50000; draw=FALSE; interpolate=FALSE; legend=TRUE; legend.only=FALSE; pax=list(); pal=list(); levels=NULL; add=FALSE; range=NULL; new=NA; breaks=NULL; coltab=NULL; facts=NULL; xlim=NULL; ylim=NULL; out <- list() out$lim <- out$ext <- as.vector(ext(x)) if (!is.null(ext)) { ext <- ext(ext) x <- crop(x, ext) out$ext <- as.vector(ext(x)) out$lim <- ext } if (!(is.null(xlim) & is.null(ylim))) { e <- as.vector(ext(x)) if (!is.null(xlim)) e[1:2] <- sort(xlim) if (!is.null(ylim)) e[3:4] <- sort(ylim) x <- crop(x, ext(e)) out$ext <- as.vector(ext(x)) out$lim <- e } out$add <- isTRUE(add) out$axs <- as.list(pax) if (is.null(out$axs$las)) out$axs$las <- las out$draw_grid <- isTRUE(grid) out$leg <- as.list(plg) out$asp <- 1 out$lonlat <- is.lonlat(x, perhaps=TRUE, warn=FALSE) if (out$lonlat) { out$asp <- 1/cos((mean(out$ext[3:4]) * pi)/180) } if (!is.null(alpha)) { if (!inherits(alpha, "SpatRaster")) { cols <- grDevices::rgb(t(grDevices::col2rgb(cols)), alpha=alpha[1]*255, maxColorValue=255) } } else { alpha <- 255 } out$cols <- cols out$coltab <- coltab out$cats <- cats out$breaks <- breaks out$breakby <- breakby out$interpolate <- FALSE out$legend_draw <- isTRUE(legend) out$legend_only <- isTRUE(legend.only) out$legend_sort <- isTRUE(sort) if (is.null(mar)) { if (out$legend_draw) { out$mar <- c(3.1, 3.1, 2.1, 7.1) } else { out$mar <- c(3.1, 3.1, 2.1, 2.1) } } else { out$mar <- rep_len(mar, 4) } if (!hasValues(x)) { out$values = FALSE warn("plot", "SpatRaster has no cell values") } else { out$values <- TRUE if (type=="factor") { out <- .as.raster.factor(out, x) } else if (type=="colortable") { out <- .as.raster.colortable(out, x) } else if (type=="classes") { out$levels <- levels out <- .as.raster.classes(out, x) } else if (type=="interval") { out <- .as.raster.interval(out, x) } else { out$interpolate <- isTRUE(interpolate) out$range <- range out <- .as.raster.continuous(out, x, type) } if (!is.null(colNA)) { if (!is.na(colNA) && out$values) { out$colNA <- grDevices::rgb(t(grDevices::col2rgb(colNA)), alpha=alpha, maxColorValue=255) out$r[is.na(out$r)] <- out$colNA } } } if (draw) { if (inherits(alpha, "SpatRaster")) { alpha <- clamp(as.vector(alpha[[1]])*255, 0, 255) out$r <- matrix(grDevices::rgb(t(grDevices::col2rgb(out$r)), alpha=alpha, maxColorValue=255), nrow=nrow(out$r), byrow=TRUE) } out <- .plotit(out, new=new, reset=reset, ...) } invisible(out) } setMethod("plot", signature(x="SpatRaster", y="numeric"), function(x, y=1, col, type, mar=NULL, legend=TRUE, axes=TRUE, plg=list(), pax=list(), maxcell=500000, smooth=FALSE, range=NULL, levels=NULL, fun=NULL, colNA=NULL, alpha=NULL, sort=FALSE, grid=FALSE, ext=NULL, reset=FALSE, ...) { y <- round(y) stopifnot((min(y) > 0) & (max(y) <= nlyr(x))) if (length(y) > 1) { x <- x[[y]] if (inherits(alpha, "SpatRaster")) { if (nlyr(alpha) > 1) { alpha <- alpha[[y]] } } plot(x, col=col, type=type, mar=mar, legend=legend, axes=axes, plg=plg, pax=pax, maxcell=maxcell/(length(x)/2), smooth=smooth, range=range, levels=levels, fun=fun, colNA=colNA, alpha=alpha, grid=grid, sort=sort, ext=ext, ...) return(invisible()) } if (inherits(alpha, "SpatRaster")) { if (!compareGeom(x, alpha, crs=FALSE, ext=FALSE, rowcol=TRUE)) { error("plot", "geometry of alpha does not match x") } } x <- x[[y]] if (ncell(x) > 1.1 * maxcell) { if (inherits(alpha, "SpatRaster")) { if (nlyr(alpha) > 1) { alpha <- alpha[[y]] } alpha <- spatSample(alpha, maxcell, ext=ext, method="regular", as.raster=TRUE) } x <- spatSample(x, maxcell, ext=ext, method="regular", as.raster=TRUE) } if (is.character(legend)) { plg$x <- legend legend <- TRUE } breaks <- list(...)$breaks coltab <- NULL cats <- NULL if (!is.null(breaks)) { type <- "interval" } else { if (missing(type)) { if (x@ptr$hasColors()) { coltab <- coltab(x)[[1]] if (is.factor(x)) { act <- activeCat(x) cats <- cats(x)[[1]][, c(1, act+1)] type <- "factor" } else { type <- "colortable" legend <- FALSE } } else if (is.factor(x)) { type <- "factor" act <- activeCat(x) cats <- cats(x)[[1]][, c(1, act+1)] } else if (is.bool(x)) { type <- "factor" levels(x) <- c("False", "True") cats <- cats(x)[[1]] } else { type <- "depends" } } else { type <- match.arg(type, c("continuous", "classes", "interval")) } } if (missing(col)) col <- rev(grDevices::terrain.colors(50)) x <- .prep.plot.data(x, type=type, cols=col, mar=mar, draw=TRUE, plg=plg, pax=pax, legend=isTRUE(legend), axes=isTRUE(axes), coltab=coltab, cats=cats, interpolate=smooth, levels=levels, range=range, colNA=colNA, alpha=alpha, reset=reset, grid=grid, sort=sort, ext=ext, ...) if (!is.null(fun)) { if (!is.null(formals(fun))) { fun(y) } else { fun() } } invisible(x) } ) setMethod("plot", signature(x="SpatRaster", y="missing"), function(x, y, maxcell=500000, main, mar=NULL, nc, nr, maxnl=16, ...) { if (x@ptr$rgb) { i <- x@ptr$getRGB() + 1 if (missing(main)) main = "" if (is.null(mar)) mar = 0 plotRGB(x, i[1], i[2], i[3], maxcell=maxcell, mar=mar, main=main, ...) return(invisible()) } nl <- max(1, min(nlyr(x), maxnl)) if (nl==1) { if (missing(main)) main = "" out <- plot(x, 1, maxcell=maxcell, main=main[1], mar=mar, ...) return(invisible(out)) } nrnc <- .get_nrnc(nr, nc, nl) old.par <- graphics::par(no.readonly = TRUE) on.exit(graphics::par(old.par)) if (is.null(mar)) { mar=c(1.5, 1.5, 1.5, 3) } graphics::par(mfrow=nrnc) maxcell=maxcell/(nl/2) if (missing("main")) { tm <- time(x) if (!any(is.na(tm))) { main <- as.character(time(x)) } else { main <- names(x) } } else { main <- rep_len(main, nl) } #if (onelegend) { legend <- FALSE } for (i in 1:nl) { plot(x, i, main=main[i], mar=mar, ...) } } ) setMethod("plot", signature(x="SpatRaster", y="character"), function(x, y, ...) { y <- match(y, names(x)) if (any(is.na(y))) { error("plot", "y does not match the names in x") } plot(x, y, ...) } ) terra/R/animate.R0000644000175000017500000000120614201035747013465 0ustar nileshnilesh setMethod("animate", signature(x="SpatRaster"), function(x, pause=0.25, main, range, maxcell=50000, n=1, ...) { if (missing(main)) { main <- names(x) } x <- spatSample(x, size=maxcell, method="regular", as.raster=TRUE) if (missing(range)) { mnmx <- minmax(x) range <- c(min(mnmx[1,]), max(mnmx[2,])) } nl <- nlyr(x) n <- max(1, round(n)) i <- 1 reps <- 0 while (reps < n) { plot(x[[i]], main = main[i], range=range, maxcell=Inf, ...) grDevices::dev.flush() Sys.sleep(pause) i <- i + 1 if (i > nl) { i <- 1 reps <- reps+1 } } } ) terra/R/rast.R0000644000175000017500000002252514201035747013027 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : October 2017 # Version 1.0 # License GPL v3 new_rast <- function(nrows=10, ncols=10, nlyrs=1, xmin=0, xmax=1, ymin=0, ymax=1, crs, extent, resolution, vals, names, time, units) { if (missing(extent)) { e <- c(xmin, xmax, ymin, ymax) } else { e <- as.vector(extent) } if ((e[1] >= e[2]) || e[3] >= e[4]) { error("rast,missing", "invalid extent") } if (missing(crs)) { if (e[1] > -360.01 & e[2] < 360.01 & e[3] > -90.01 & e[4] < 90.01) { crs <- "OGC:CRS84" } else { crs <- "" } } else { crs <- character_crs(crs, "rast") } #check_proj4_datum(crs) r <- methods::new("SpatRaster") r@ptr <- SpatRaster$new(c(nrows, ncols, nlyrs), e, crs) r <- messages(r, "rast") if (!missing(resolution)) { res(r) <- resolution } if (!missing(names)) { names(r) <- names } if (!missing(vals)) { if (length(vals) == 1) { if (is.na(vals[1])) { vals <- as.numeric(NA) } } values(r) <- vals } if (!missing(time)) { time(r) <- time } if (!missing(units)) { time(r) <- units } r } setMethod("rast", signature(x="missing"), function(x, nrows=180, ncols=360, nlyrs=1, xmin=-180, xmax=180, ymin=-90, ymax=90, crs, extent, resolution, vals, names, time, units) { new_rast(nrows, ncols, nlyrs, xmin, xmax, ymin, ymax, crs, extent, resolution, vals, names, time, units) } ) setMethod("rast", signature(x="stars"), function(x) { x <- from_stars(x) if (inherits(x, "SpatRasterDataset")) { rast(x) } else { x } } ) setMethod("rast", signature(x="stars_proxy"), function(x) { x <- from_stars(x) if (inherits(x, "SpatRasterDataset")) { rast(x) } else { x } } ) setMethod("rast", signature(x="list"), function(x) { i <- sapply(x, function(i) inherits(i, "SpatRaster")) if (!all(i)) { if (!any(i)) { error("rast,list", "none of the elements of x are a SpatRaster") } else { warn("rast", sum(!i), " out of ", length(x), " elements of x are not a SpatRaster") x <- x[i] } } # start with an empty raster (alternatively use a deep copy) out <- rast(x[[1]]) opt <- spatOptions() for (i in 1:length(x)) { out@ptr$addSource(x[[i]]@ptr, FALSE, opt) } out <- messages(out, "rast") lnms <- names(x) i <- lnms != "" if (any(i)) { rnms <- names(out) rnms[lnms != ""] <- lnms[lnms != ""] names(out) <- rnms } out } ) setMethod("rast", signature(x="SpatExtent"), function(x, ...) { dots <- list(...) dots$xmin=x[1] dots$xmax=x[2] dots$ymin=x[3] dots$ymax=x[4] do.call(new_rast, dots) } ) setMethod("rast", signature(x="SpatVector"), function(x, ...) { dots <- list(...) e <- ext(x) dots$xmin=e[1] dots$xmax=e[2] dots$ymin=e[3] dots$ymax=e[4] if (all(is.na(pmatch(names(dots), "crs")))) { dots$crs <- crs(x) } do.call(new_rast, dots) } ) .fullFilename <- function(x, mustExist=TRUE) { x <- trimws(x) p <- normalizePath(x, winslash = "/", mustWork = FALSE) if (mustExist) { i <- file.exists(p) if (all(i)) { return(p) } else { x[i] <- p[i] } } else { return(p) } #if (identical(basename(x), x)) { # x <- file.path(getwd(), x) #} #if (expand) { # x <- path.expand(x) #} return(x) } setMethod("rast", signature(x="character"), function(x, subds=0, lyrs=NULL, opts=NULL) { x <- trimws(x) x <- x[x!=""] if (length(x) == 0) { error("rast", "filename is empty. Provide a valid filename") } r <- methods::new("SpatRaster") f <- .fullFilename(x) f <- enc2utf8(f) #subds <- subds[1] if (is.null(opts)) opts <- ""[0] if (length(subds) == 0) subds = 0 if (is.character(subds)) { #r@ptr <- SpatRaster$new(f, -1, subds, FALSE, 0[]) r@ptr <- SpatRaster$new(f, -1, subds, FALSE, opts, 0[]) } else { r@ptr <- SpatRaster$new(f, subds-1, "", FALSE, opts, 0[]) } r <- messages(r, "rast") if (r@ptr$getMessage() == "ncdf extent") { test <- try(r <- .ncdf_extent(r), silent=TRUE) if (inherits(test, "try-error")) { warn("rast", "GDAL did not find an extent. Cells not equally spaced?") } } r <- messages(r, "rast") if (crs(r) == "") { if (is.lonlat(r, perhaps=TRUE, warn=FALSE)) { crs(r) <- "OGC:CRS84" } } if (!is.null(lyrs)) { r[[lyrs]] } else { r } } ) multi <- function(x, subds=0, xyz=c(1,2,3)) { x <- trimws(x) x <- x[x!=""] if (length(x) == 0) { error("rast,character", "provide a valid filename") } r <- methods::new("SpatRaster") f <- .fullFilename(x) #subds <- subds[1] if (is.character(subds)) { r@ptr <- SpatRaster$new(f, -1, subds, TRUE, xyz-1) } else { r@ptr <- SpatRaster$new(f, subds-1, "", TRUE, xyz-1) } if (r@ptr$getMessage() == "ncdf extent") { test <- try(r <- .ncdf_extent(r), silent=TRUE) if (inherits(test, "try-error")) { warn("rast", "GDAL did not find an extent. Cells not equally spaced?") } } r <- messages(r, "rast") if (crs(r) == "") { if (is.lonlat(r, perhaps=TRUE, warn=FALSE)) { crs(r) <- "OGC:CRS84" } } r } setMethod("rast", signature(x="SpatRaster"), function(x, nlyrs=nlyr(x), names, vals, keeptime=TRUE, keepunits=FALSE, props=FALSE) { x@ptr <- x@ptr$geometry(nlyrs, props, keeptime, keepunits) x <- messages(x, "rast") if (!missing(names)) { if (length(names) == nlyr(x)) names(x) <- names } if (!missing(vals)) { values(x) <- vals } x } ) setMethod("rast", signature(x="SpatRasterDataset"), function(x) { if (length(x) == 0) { error("rast", "empty SpatRasterDataset") } else if (length(x) == 1) { x[1] } else { r <- methods::new("SpatRaster") r@ptr <- x@ptr$collapse() nms <- names(x) if (any(nms != "")) { names(r) <- paste(rep(nms, nlyr(x)), names(r), sep="_") } r } } ) setMethod("rast", signature(x="array"), function(x, crs="", extent=NULL) { dims <- dim(x) if (length(dims) > 3) { if (length(dims) == 4) { if (dims[4] == 1) { x <- x[,,,1] } else { error("rast,array", "rast cannot handle an array with 4 dimensions (try 'sds')") } } else { error("rast,array", "cannot handle an array with more than 3 dimensions") } } r <- methods::new("SpatRaster") if (!is.null(extent)) { e <- as.vector(extent) } else { e <- c(0, dims[2], 0, dims[1]) } crs <- character_crs(crs, "rast") r@ptr <- SpatRaster$new(dims, e, crs) values(r) <- x messages(r, "rast") } ) setMethod("rast", signature(x="ANY"), function(x, ...) { methods::as(x, "SpatRaster") } ) .rastFromXYZ <- function(xyz, digits=6, crs="", extent=NULL) { if (!is.null(extent)) { warn("rast", 'argument "extent" is ignored if type="xyz"') } ln <- colnames(xyz) ## xyz might not have colnames, or might have "" names if (is.null(ln)) ln <- rep("", ncol(xyz)) if (any(nchar(ln) < 1)) ln <- make.names(ln) if (inherits(xyz, "data.frame")) { xyz <- as.matrix(xyz) xyz <- matrix(as.numeric(xyz), ncol=ncol(xyz), nrow=nrow(xyz)) } x <- sort(unique(xyz[,1])) dx <- x[-1] - x[-length(x)] rx <- min(dx) for (i in 1:5) { rx <- rx / i q <- sum(round(dx / rx, digits=digits) %% 1) if ( q == 0 ) { break } } if ( q > 0 ) { error("raster,matrix(xyz)", "x cell sizes are not regular") } y <- sort(unique(xyz[,2])) dy <- y[-1] - y[-length(y)] # probably a mistake to use the line below # Gareth Davies suggested that it be removed # dy <- round(dy, digits) ry <- min(dy) for (i in 1:5) { ry <- ry / i q <- sum(round(dy / ry, digits=digits) %% 1) if ( q == 0 ) { break } } if ( q > 0 ) { error("raster,matrix(xyz)", "y cell sizes are not regular") } minx <- min(x) - 0.5 * rx maxx <- max(x) + 0.5 * rx miny <- min(y) - 0.5 * ry maxy <- max(y) + 0.5 * ry d <- dim(xyz) r <- rast(xmin=minx, xmax=maxx, ymin=miny, ymax=maxy, crs=crs, nlyrs=d[2]-2) res(r) <- c(rx, ry) ext(r) <- round(ext(r), digits+2) cells <- cellFromXY(r, xyz[,1:2]) if (d[2] > 2) { names(r) <- ln[-c(1:2)] v <- matrix(NA, nrow=ncell(r), ncol= nlyr(r)) v[cells, ] <- xyz[, -c(1:2)] values(r) <- v } return(r) } setMethod("rast", signature(x="matrix"), function(x, type="", crs="", digits=6, extent=NULL) { stopifnot(prod(dim(x)) > 0) if (type == "xyz") { r <- .rastFromXYZ(x, crs=crs, digits=digits, extent=extent) } else { if (is.null(extent)) { r <- rast(nrows=nrow(x), ncols=ncol(x), extent=ext(c(0, ncol(x), 0, nrow(x))), crs=crs) } else { r <- rast(nrows=nrow(x), ncols=ncol(x), crs=crs, extent=extent) } values(r) <- as.vector(t(x)) } messages(r, "rast") } ) setMethod("rast", signature(x="data.frame"), function(x, type="xyz", crs="", digits=6, extent=NULL) { if (type == "xyz") { .rastFromXYZ(x, crs=crs, digits=digits, extent=extent) } else { rast(as.matrix(x), type=type, crs=crs, digits=digits, extent=extent) } } ) setMethod("NAflag<-", signature(x="SpatRaster"), function(x, value) { value <- as.numeric(value) if (!(x@ptr$setNAflag(value))) { error("NAflag<-", "cannot set this value") } x } ) setMethod("NAflag", signature(x="SpatRaster"), function(x) { x@ptr$getNAflag() } ) terra/R/clean.R0000644000175000017500000000227214201035747013135 0ustar nileshnilesh ..gaps <- function(x) { p <- as.polygons(floor(ext(x)+1), crs=crs(x)) e <- disagg(erase(p, x)) if (nrow(e) > 1) { xmin = ext(p)[1] i <- sapply(1:nrow(e), function(i) ext(e[i])[1] > xmin) e <- e[i] x <- rbind(x, e) } x } clean_further <- function(x, tolerance=0.0001) { out <- as.lines(x) out <- snap(out, tolerance) out <- makeNodes(out) out <- mergeLines(out) as.polygons(out) } clean <- function(x) { g <- gaps(x) out <- erase(x) out <- rbind(out, g) g <- gaps(out) rbind(out, g) } mergebyborder <- function(x, field) { i <- is.na(x[[field, drop=TRUE]]) if (!any(i)) return(x) s <- sharedPaths(x) s$length <- perim(s) from <- x[i] x <- x[!i] for (i in 1:nrow(from)) { } } centerline <- function(p) { v <- as.points(voronoi(p, tolerance=0)) v <- intersect(v, p) v } #library(terra); messages = terra:::messages #p <- vect(system.file("ex/lux.shp", package="terra")) #h <- convHull(p[-12], "NAME_1") #x <- clean(h) #y <- clean_further(x) #hh <- rbind(h, h) #e <- erase(hh) #g <- gaps(e) #v1 = as.polygons(ext(0,1,0,1)) #v2 = as.polygons(ext(1.01,2,0,1)) #v <- rbind(v1, v2) #s = snap(v) terra/R/vect.R0000644000175000017500000002316014201035747013013 0ustar nileshnilesh #setMethod("row.names", signature(x="SpatVector"), # function(x) { # 1:nrow(x) # } #) character_crs <- function(crs, caller="") { if (is.na(crs)) { "" } else if (!inherits(crs, "character")) { warn(caller, "argument 'crs' should be a character value") as.character(crs) } else { crs } } setMethod("as.vector", signature(x="SpatVector"), function(x, mode="any") { if (nrow(x) > 0) { lapply(1:nrow(x), function(i) x[i,]) } else { x } } ) setMethod("vect", signature(x="missing"), function(x) { p <- methods::new("SpatVector") p@ptr <- SpatVector$new() messages(p, "vect") return(p) } ) setMethod("vect", signature(x="character"), function(x, layer="", query="", extent=NULL, filter=NULL, crs="", proxy=FALSE) { p <- methods::new("SpatVector") s <- substr(x[1], 1, 5) if (s %in% c("POINT", "MULTI", "LINES", "POLYG")) { # if (all(grepl("\\(", x) & grepl("\\)", x))) { x <- gsub("\n", "", x) p@ptr <- SpatVector$new(x) crs(p) <- crs } else { p@ptr <- SpatVector$new() nx <- try(normalizePath(x, mustWork=TRUE), silent=TRUE) if (!inherits(nx, "try-error")) { # skip html x <- nx x <- enc2utf8(x) } proxy <- isTRUE(proxy) #if (proxy) query <- "" if (is.null(filter)) { filter <- vect()@ptr } else { if (proxy) { error("vect", "you cannot use 'filter' when proxy=TRUE") } filter <- filter@ptr } if (is.null(extent)) { extent <- double() } else { extent <- as.vector(ext(extent)) } p@ptr$read(x, layer, query, extent, filter, proxy) if (isTRUE(crs != "")) { crs(p) <- crs } if (proxy) { messages(p, "vect") pp <- methods::new("SpatVectorProxy") pp@ptr <- SpatVectorProxy$new() pp@ptr$v <- p@ptr return(pp) } } messages(p, "vect") } ) setMethod("vect", signature(x="Spatial"), function(x, ...) { methods::as(x, "SpatVector") } ) setMethod("vect", signature(x="sf"), function(x) { methods::as(x, "SpatVector") } ) setMethod("vect", signature(x="sfc"), function(x) { methods::as(x, "SpatVector") } ) setMethod("vect", signature(x="XY"), #sfg function(x) { methods::as(x, "SpatVector") } ) .checkXYnames <- function(x, warn=FALSE) { if (is.null(x)) return(TRUE) if (length(x) != 2) { error("vect", "coordinate matrix should have 2 columns") } z <- tolower(x[1:2]) x <- substr(z, 1, 3) y <- substr(x, 1, 1) if ((y[1] == "x") & (y[2] == "y")) return(FALSE) if ((x[1] == "eas") & (x[2] == "nor")) return(FALSE) if ((x[1] == "lon") & (x[2] == "lat")) return(TRUE) if (grepl("lon", z[1]) & grepl("lat", z[2])) return(TRUE) if ((x[1] == "lat") | (x[2] == "lon")) { error("vect", "longitude/latitude in the wrong order") } else if ((y[1] == "y") | (y[2] == "x")) { error("vect", "x/y in the wrong order") } else if ((x[1] == "nor") | (x[2] == "eas")) { error("vect", "easting/northing in the wrong order") } else if (warn) { warn("coordinate names not recognized. Expecting lon/lat, x/y, or easting/northing") } return(FALSE) } setMethod("vect", signature(x="matrix"), function(x, type="points", atts=NULL, crs="") { type <- tolower(type) type <- match.arg(tolower(type), c("points", "lines", "polygons")) stopifnot(NCOL(x) > 1) crs <- character_crs(crs, "vect") p <- methods::new("SpatVector") p@ptr <- SpatVector$new() crs(p) <- crs nr <- nrow(x) if (nr == 0) { return(p) } if (ncol(x) == 2) { lonlat <- .checkXYnames(colnames(x)) if (type == "points") { p@ptr$setPointsXY(as.double(x[,1]), as.double(x[,2])) } else { p@ptr$setGeometry(type, rep(1, nr), rep(1, nr), x[,1], x[,2], rep(FALSE, nr)) } if (lonlat && isTRUE(crs=="")) crs <- "+proj=longlat" } else if (ncol(x) == 4) { #.checkXYnames(colnames(x)[3:4]) p@ptr$setGeometry(type, x[,1], x[,2], x[,3], x[,4], rep(FALSE, nr)) } else if (ncol(x) == 5) { #.checkXYnames(colnames(x)[3:4]) p@ptr$setGeometry(type, x[,1], x[,2], x[,3], x[,4], x[,5]) } else { error("vect", "not an appropriate matrix") } if (!is.null(atts)) { if ((nrow(atts) == nrow(p)) & (ncol(atts) > 0)) { values(p) <- atts } } messages(p, "vect") } ) setMethod("$", "SpatVector", function(x, name) { s <- .subset_cols(x, name, drop=TRUE) s[,1,drop=TRUE] }) setMethod("[[", c("SpatVector", "numeric", "missing"), function(x, i, j, ... ,drop=FALSE) { s <- .subset_cols(x, i, ..., drop=TRUE) s[,,drop=drop] }) setMethod("[[", c("SpatVector", "character", "missing"), function(x, i, j, ... ,drop=FALSE) { s <- .subset_cols(x, i, ..., drop=TRUE) s[,,drop=drop] }) setReplaceMethod("[", c("SpatVector", "ANY", "ANY"), function(x, i, j, value) { v <- values(x) v[i,j] <- value if (nrow(v) != nrow(x)) { error("[<-", "this would create an invalid SpatVector") } values(x) <- v x } ) setReplaceMethod("[", c("SpatVector", "ANY", "missing"), function(x, i, j, value) { v <- values(x) if (inherits(value, "SpatVector")) { value <- values(value) } v[i,] <- value if (nrow(v) != nrow(x)) { error("[<-", "this would create an invalid SpatVector") } values(x) <- v x } ) setReplaceMethod("[", c("SpatVector", "missing", "ANY"), function(x, i, j, value) { v <- values(x) if (inherits(value, "SpatVector")) { value <- values(value) } v[,j] <- value if (nrow(v) != nrow(x)) { error("[<-", "this would create an invalid SpatVector") } values(x) <- v x } ) setReplaceMethod("[[", c("SpatVector", "character", "missing"), function(x, i, j, value) { x@ptr <- x@ptr$deepcopy() if (is.null(value)) { for (name in i) { if (name %in% names(x)) { x@ptr$remove_column(name) } } return(x); } if (length(i) > 1) { error("[[<-", "you can only set one variable at a time") } name <- i[1] value <- rep(value, length.out=nrow(x)) if (name %in% names(x)) { d <- values(x) d[[name]] <- value values(x) <- d } else { if (is.integer(value)) { ok <- x@ptr$add_column_long(value, name) } else if (is.numeric(value)) { ok <- x@ptr$add_column_double(value, name) } else { ok <- x@ptr$add_column_string(as.character(value), name) } if (!ok) { error("[[<-,SpatVector", "cannot set these values") } } x } ) setReplaceMethod("[[", c("SpatVector", "numeric", "missing"), function(x, i, j, value) { stopifnot(i > 0 && i <= ncol(x)) vn <- names(x)[i] x[[vn]] <- value x } ) setMethod("$<-", "SpatVector", function(x, name, value) { x[[name]] <- value x } ) setMethod("vect", signature(x="data.frame"), function(x, geom=c("lon", "lat"), crs=NA) { if (!all(geom %in% names(x))) { error("vect", "the variable name(s) in argument `geom` are not in `x`") } crs <- character_crs(crs, "vect") if (length(geom) == 2) { geom <- match(geom[1:2], names(x)) cls <- sapply(x[, geom], class) if (cls[1] == "integer") { x[,geom[1]] = as.numeric(x[,geom[1]]) } if (cls[2] == "integer") { x[,geom[2]] = as.numeric(x[,geom[2]]) } p <- methods::new("SpatVector") p@ptr <- SpatVector$new() x <- .makeSpatDF(x) p@ptr$setPointsDF(x, geom-1, crs) messages(p, "vect") return(p) } else if (length(geom) == 1) { v <- vect(unlist(x[,geom]), crs=crs) } else { error("vect", "the length of 'geom' must be 1 or 2") } values(v) <- x v } ) setMethod("vect", signature(x="list"), function(x) { x <- svc(x) x <- x@ptr$append() v <- methods::new("SpatVector") v@ptr <- x messages(v, "vect") } ) setMethod("query", signature(x="SpatVectorProxy"), function(x, start=1, n=nrow(x), vars=NULL, where=NULL, extent=NULL, filter=NULL) { f <- x@ptr$v$source layer <- x@ptr$v$layer e <- x@ptr$v$read_extent if (is.null(extent)) { if (length(e) == 4) { extent = ext(e); } } else { if (length(e) == 4) { extent = intersect(ext(e), extent); if (is.null(extent)) { error("query", "extent does not intersect with x") } } } if (is.null(vars)) { vars <- "*" } else { vars <- na.omit(unique(vars)) nms <- names(x) if (!all(vars %in% nms)) { error("query", "not all vars are variable names") } else if (length(vars) < length(nms)) { vars <- paste(vars, collapse=", ") } } qy <- "" if (!is.null(where)) { qy <- paste("SELECT", vars, "FROM", layer, "WHERE", where[1]) } nr <- nrow(x) start <- start-1 if (start > 0) { if (qy == "") { qy <- paste("SELECT", vars, "FROM", layer) } if (n >= (nr-start)) { qy <- paste(qy, "OFFSET", start) } else { n <- min(n, nr-start) qy <- paste(qy, layer, "LIMIT", n, "OFFSET", start) } } else if (n < nr) { if (qy == "") { qy <- paste("SELECT", vars, "FROM", layer) } n <- min(n, nr) qy <- paste(qy, "LIMIT", n) } if ((qy != "") && (x@ptr$v$read_query != "")) { error("query", "A query was used to create 'x'; you can only subset it with extent or filter") } vect(f, layer, query=qy, extent=extent, filter=filter, crs="", FALSE) } ) vector_layers <- function(filename, delete="", return_error=FALSE) { p <- SpatVector$new() if (any(delete != "")) { delete <- trimws(delete) ok <- p$delete_layers(filename, delete, return_error[1]) messages(p, "vector_layers") invisible(ok) } else { out <- p$layer_names(filename) messages(p, "vector_layers") out } } terra/R/focalMat.R0000644000175000017500000000340514201035747013600 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : June 2013 # Version 1.0 # License GPL v3 .circular.weight <- function(rs, d, fillNA=FALSE) { nx <- 1 + 2 * floor(d/rs[1]) ny <- 1 + 2 * floor(d/rs[2]) m <- matrix(ncol=nx, nrow=ny) m[ceiling(ny/2), ceiling(nx/2)] <- 1 if ((nx != 1) || (ny != 1)) { x <- rast(m, crs="+proj=utm +zone=1 +datum=WGS84") ext(x) <- c(xmin=0, xmax=nx*rs[1], ymin=0, ymax=ny*rs[2]) d <- as.matrix(distance(x), wide=TRUE) <= d m <- d / sum(d) } if (fillNA) { m[m <= 0] <- NA } m } .Gauss.weight <- function(rs, sigma) { if (length(sigma) == 1) { d <- 3 * sigma } else { d <- sigma[2] sigma <- sigma[1] } nx <- 1 + 2 * floor(d/rs[1]) ny <- 1 + 2 * floor(d/rs[2]) m <- matrix(ncol=nx, nrow=ny) xr <- (nx * rs[1]) / 2 yr <- (ny * rs[2]) / 2 r <- rast(m, crs="+proj=utm +zone=1 +datum=WGS84") ext(r) <- c(xmin=-xr[1], xmax=xr[1], ymin=-yr[1], ymax=yr[1]) p <- xyFromCell(r, 1:ncell(r))^2 # according to http://en.wikipedia.org/wiki/Gaussian_filter m <- 1/(2*pi*sigma^2) * exp(-(p[,1]+p[,2])/(2*sigma^2)) m <- matrix(m, ncol=nx, nrow=ny, byrow=TRUE) # sum of weights should add up to 1 m / sum(m) } .rectangle.weight <- function(rs, d) { d <- rep(d, length.out=2) nx <- 1 + 2 * floor(d[1]/rs[1]) ny <- 1 + 2 * floor(d[2]/rs[2]) m <- matrix(1, ncol=nx, nrow=ny) m / sum(m) } focalMat <- function(x, d, type=c('circle', 'Gauss', 'rectangle'), fillNA=FALSE) { type <- match.arg(type) x <- res(x) if (type == 'circle') { .circular.weight(x, d[1], fillNA) } else if (type == 'Gauss') { if (!length(d) %in% 1:2) { error("focalMath", "if type=Gauss, d should be a vector of length 1 or 2") } .Gauss.weight(x, d) } else { .rectangle.weight(x, d) } } terra/R/colors.R0000644000175000017500000000267514201035747013363 0ustar nileshnilesh setMethod ("coltab" , "SpatRaster", function(x) { hascols <- x@ptr$hasColors() if (any(hascols)) { d <- x@ptr$getColors() d <- lapply(d, .getSpatDF) d[!hascols] <- list(NULL) } else { d <- vector("list", length(hascols)) } d } ) setMethod ("coltab<-" , "SpatRaster", function(x, layer=1, value) { x@ptr <- x@ptr$deepcopy() if (missing(value)) { value <- layer layer <- 1 } layer <- layer[1]-1 if (is.null(value)) { x@ptr$removeColors(layer) return(x) } if (inherits(value, "list")) { value <- value[[1]] } if (inherits(value, "character")) { value <- t(grDevices::col2rgb(value, alpha=TRUE)) } if (inherits(value, "character")) { value <- data.frame(t(grDevices::col2rgb(value, alpha=TRUE))) } else if (inherits(value, "matrix")) { value <- data.frame(value) } stopifnot(inherits(value, "data.frame")) nms <- tolower(names(value)) if (!("value" %in% nms)) { value <- cbind(values=(1:nrow(value))-1, value) } #value <- value[1:256,] if (ncol(value) == 4) { value <- cbind(value, alpha=255) } value[, 1] <- as.integer(value[, 1]) for (i in 2:ncol(value)) { value[, i] <- as.integer(clamp(value[, i], 0, 255)) } value[is.na(value)] <- 255 d <- .makeSpatDF(value) if (x@ptr$setColors(layer, d)) { return(x) } else { error("coltab<-", "cannot set these values") } } ) terra/R/zonal.R0000644000175000017500000000446414201035747013203 0ustar nileshnilesh setMethod("zonal", signature(x="SpatRaster", z="SpatRaster"), function(x, z, fun="mean", ..., as.raster=FALSE, filename="", wopt=list()) { if (nlyr(z) > 1) { z <- z[[1]] } zname <- names(z) txtfun <- .makeTextFun(match.fun(fun)) if (inherits(txtfun, "character") && (txtfun %in% c("max", "min", "mean", "sum"))) { na.rm <- isTRUE(list(...)$na.rm) opt <- spatOptions() ptr <- x@ptr$zonal(z@ptr, txtfun, na.rm, opt) messages(ptr, "zonal") out <- .getSpatDF(ptr) } else { nl <- nlyr(x) res <- list() vz <- values(z) nms <- names(x) for (i in 1:nl) { d <- stats::aggregate(values(x[[i]]), list(zone=vz), fun, ...) colnames(d)[2] <- nms[i] res[[i]] <- d } out <- res[[1]] if (nl > 1) { for (i in 2:nl) { out <- merge(out, res[[i]]) } } } if (as.raster) { if (is.null(wopt$names)) { wopt$names <- names(x) } subst(z, out[,1], out[,-1], filename=filename, wopt=wopt) } else { if (is.factor(z)) { levs <- active_cats(z)[[1]] m <- match(out$zone, levs[,1]) out$zone <- levs[m, 2] } colnames(out)[1] <- zname out } } ) setMethod("global", signature(x="SpatRaster"), function(x, fun="mean", weights=NULL, ...) { nms <- names(x) nms <- make.unique(nms) txtfun <- .makeTextFun(fun) opt <- spatOptions() if (!is.null(weights)) { stopifnot(inherits(weights, "SpatRaster")) stopifnot(txtfun %in% c("mean", "sum")) na.rm <- isTRUE(list(...)$na.rm) ptr <- x@ptr$global_weighted_mean(weights@ptr, txtfun, na.rm, opt) messages(ptr, "global") res <- (.getSpatDF(ptr)) rownames(res) <- nms return(res) } if (inherits(txtfun, "character")) { if (txtfun %in% c("max", "min", "mean", "sum", "range", "rms", "sd", "sdpop", "notNA", "isNA")) { na.rm <- isTRUE(list(...)$na.rm) ptr <- x@ptr$global(txtfun, na.rm, opt) messages(ptr, "global") res <- .getSpatDF(ptr) rownames(res) <- nms return(res) } } nl <- nlyr(x) res <- list() for (i in 1:nl) { res[[i]] <- fun(values(x[[i]]) , ...) } res <- do.call(rbind,res) res <- data.frame(res) if ((ncol(res) == 1) && (colnames(res) == "res")) { colnames(res) <- "global" } rownames(res) <- nms res } ) terra/R/autocor.R0000644000175000017500000001351114201035747013525 0ustar nileshnilesh# Author: Robert J. Hijmans # Date : April 2011 / Jan 2021 # Version 1.0 # License GPL v3 .checkngb <- function(ngb, mustBeOdd=FALSE) { ngb <- as.integer(round(ngb)) if (length(ngb) == 1) { ngb <- c(ngb, ngb) } else if (length(ngb) > 2) { error("autocor", "ngb should be a single value or two values") } if (min(ngb) < 1) { stop("ngb should be larger than 1") } if (mustBeOdd) { if (any(ngb %% 2 == 0)) { error("autocor", "neighborhood size must be an odd number") } } return(ngb) } .getFilter <- function(w, warn=TRUE) { if (!is.matrix(w)) { w <- .checkngb(w) w <- matrix(1, nrow=w[1], ncol=(w[2])) w[ceiling(dim(w)[1]/2), ceiling(dim(w)[2]/2)] <- 0 } else { if (w[ceiling(dim(w)[1]/2), ceiling(dim(w)[2]/2)] != 0) { if (warn) { warning('central cell of weights matrix (filter) was set to zero') } w[ceiling(dim(w)[1]/2), ceiling(dim(w)[2]/2)] <- 0 } stopifnot(all(w >= 0)) } if (min(dim(w) %% 2)==0) { stop('dimensions of weights matrix (filter) must be uneven') } w } setMethod("autocor", signature(x="numeric"), function(x, w, method="moran") { method <- match.arg(tolower(method), c("moran", "geary", "gi", "gi*", "mean", "locmor")) if (all(is.na(x))) { error("autocor", "all values are NA") } if (any(is.na(w))) { error("autocor", "NA value(s) in the weight matrix") } d <- dim(w) n <- length(x) if ((d[1] != d[2]) || (d[1] != n)) { error("autocor", "w must be a square matrix with sides the size of x") } if (method %in% c("moran", "geary", "locmor", "gi")) { if (any(as.numeric(diag(w)) != 0)) { warn("autocor", paste("it is unexpected that a weight matrix for", method, "has diagonal values that are not zero")) } } else if (method %in% c("gi*")) { if (any(as.numeric(diag(w)) == 0)) { warn("autocor", paste("it is unexpected that a weight matrix for", method, "has diagonal values that are zero")) } } if (method == "moran") { dx <- x - mean(x, na.rm=TRUE) pm <- matrix(rep(dx, each=n) * dx, ncol=n) (n / sum(dx^2)) * sum(pm * w) / sum(w) } else if (method == "geary") { # geary dx <- x - mean(x, na.rm=TRUE) pm <- matrix(rep(dx, each=n) - dx, ncol=n)^2 ((n-1)/sum((dx)^2)) * sum(w * pm) / (2 * sum(w)) } else if (method == "gi") { if (any(as.numeric(diag(w)) != 0)) { warn("autocor", "it is unexpected that a weight matrix for Gi has diagonal values that are not zero") } diag(w) <- 0 sumxminx <- sum(x, na.rm=TRUE) - x Gi <- colSums(x * w) / sumxminx Ei <- rowSums(w) / (n-1) # variance following spdep::localG xibar <- sumxminx/(n - 1) si2 <- (sum(x^2) - x^2)/(n - 1) - xibar^2 VG <- si2 * (((n - 1) * rowSums(w^2) - rowSums(w)^2)/(n - 2)) VG <- VG/((sumxminx)^2) (Gi-Ei)/sqrt(VG) } else if (method == "gi*") { if (any(as.numeric(diag(w)) == 0)) { warn("autocor", "it is unexpected that a weight matrix for Gi* has diagonal values that are zero") } Gi <- colSums(x * w) / sum(x) Ei <- rowSums(w) / n # variance following spdep::localG si2 <- sum(scale(x, scale = FALSE)^2)/n VG <- (si2 * ((n * rowSums(w^2) - rowSums(w)^2)/(n - 1))) / (sum(x)^2) (Gi-Ei)/sqrt(VG) } else if (method == "locmor") { if (any(as.numeric(diag(w)) != 0)) { warn("autocor", "it is unexpected that a weight matrix for local Moran has diagonal values that are not zero") } z <- x - mean(x, na.rm=TRUE) mp <- z / ( (sum(z^2, na.rm=TRUE) / length(x)) ) mp * apply(w, 1, function(i) { sum(z * i, na.rm=TRUE) } ) } else if (method == "mean") { j <- is.na(x) x[j] <- 0 w[j,j] <- 0 m <- apply(w, 1, function(i) { sum(x * i) / sum(i)} ) m[j] <- NA m } } ) setMethod("autocor", signature(x="SpatRaster"), function(x, w=matrix(c(1,1,1,1,0,1,1,1,1),3), method="moran", global=TRUE) { method <- match.arg(tolower(method), c("moran", "geary")) if (nlyr(x) > 1) { warn("autocor", "only the first layer of x is used") x <- x[[1]] } if (global) { if (method == "moran") { z <- x - unlist(global(x, "mean", na.rm=TRUE)) wZiZj <- focal(z, w=w, fun="sum", na.rm=TRUE) wZiZj <- wZiZj * z wZiZj <- unlist(global(wZiZj, "sum", na.rm=TRUE)) z2 <- unlist(global(z*z, "sum", na.rm=TRUE)) n <- ncell(z) - unlist(global(is.na(z), "sum")) zz <- ifel(is.na(x), NA, 1) W <- focal( zz, w=w, fun="sum") NS0 <- n / unlist(global(W, "sum", na.rm=TRUE)) m <- NS0 * wZiZj / z2 names(m) <- names(x) m } else { # geary w <- .getFilter(w, warn=FALSE) i <- trunc(length(w)/2)+1 n <- ncell(x) - unlist(global(is.na(x), "sum")) fun <- function(x,...) sum((x-x[i])^2, ...) f <- focal(x, w=dim(w), fun=fun, na.rm=TRUE) Eij <- unlist(global(f, "sum", na.rm=TRUE)) xx <- ifel(is.na(x), NA ,1) W <- focal(xx, w=w, na.rm=TRUE ) z <- 2 * unlist(global(W, "sum", na.rm=TRUE)) * unlist(global((x - unlist(global(x, "mean", na.rm=TRUE)))^2, "sum", na.rm=TRUE)) g <- (n-1)*Eij/z names(g) <- names(x) g } } else { # local if (method == "moran") { z <- x - unlist(global(x, "mean", na.rm=TRUE)) zz <- ifel(is.na(x), NA, 1) W <- focal(zz, w=w, na.rm=TRUE) lz <- focal(z, w=w, na.rm=TRUE) / W n <- ncell(x) - unlist(global(is.na(x), "sum")) s2 <- unlist(global(x, "sd", na.rm=TRUE)^2) m <- (z / s2) * lz names(m) <- names(x) m } else { w <- .getFilter(w) i <- trunc(length(w)/2)+1 fun <- function(x,...) sum((x-x[i])^2, ...) Eij <- focal(x, w=dim(w), fun=fun, na.rm=TRUE) s2 <- unlist(global(x, "sd", na.rm=TRUE))^2 n <- ncell(x) - unlist(global(is.na(x), "sum")) g <- Eij / s2 names(g) <- names(x) g } } } ) terra/R/RcppExports.R0000644000175000017500000000575514201035747014355 0ustar nileshnilesh# Generated by using Rcpp::compileAttributes() -> do not edit by hand # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 proj_version <- function() { .Call(`_terra_proj_version`) } hex2rgb <- function(s) { .Call(`_terra_hex2rgb`, s) } rgb2hex <- function(x) { .Call(`_terra_rgb2hex`, x) } .sameSRS <- function(x, y) { .Call(`_terra_sameSRS`, x, y) } .SRSinfo <- function(s) { .Call(`_terra_getCRSname`, s) } .getLinearUnits <- function(s) { .Call(`_terra_getLinearUnits`, s) } .geotransform <- function(fname) { .Call(`_terra_geotransform`, fname) } .gdalinfo <- function(filename, options, oo) { .Call(`_terra_ginfo`, filename, options, oo) } .sdinfo <- function(filename) { .Call(`_terra_sd_info`, filename) } .gdal_version <- function() { .Call(`_terra_gdal_version`) } .geos_version <- function(runtime = FALSE, capi = FALSE) { .Call(`_terra_geos_version`, runtime, capi) } .metadata <- function(filename) { .Call(`_terra_metatdata`, filename) } .sdsmetadata <- function(filename) { .Call(`_terra_sdsmetatdata`, filename) } .parsedsdsmetadata <- function(filename) { .Call(`_terra_sdsmetatdataparsed`, filename) } .gdaldrivers <- function() { .Call(`_terra_gdal_drivers`) } .set_gdal_warnings <- function(level) { invisible(.Call(`_terra_set_gdal_warnings`, level)) } .gdalinit <- function(path) { invisible(.Call(`_terra_gdal_init`, path)) } .precRank <- function(x, y, minc, maxc, tail) { .Call(`_terra_percRank`, x, y, minc, maxc, tail) } .setGDALCacheSizeMB <- function(x) { invisible(.Call(`_terra_setGDALCacheSizeMB`, x)) } .getGDALCacheSizeMB <- function() { .Call(`_terra_getGDALCacheSizeMB`) } .get_proj_search_paths <- function() { .Call(`_terra_get_proj_search_paths`) } .set_proj_search_paths <- function(paths) { .Call(`_terra_set_proj_search_paths`, paths) } .PROJ_network <- function(enable, url) { .Call(`_terra_PROJ_network`, enable, url) } dist_lonlat <- function(lon1, lat1, lon2, lat2) { .Call(`_terra_dist_lonlat`, lon1, lat1, lon2, lat2) } dir_lonlat <- function(lon1, lat1, lon2, lat2) { .Call(`_terra_dir_lonlat`, lon1, lat1, lon2, lat2) } dist2track <- function(lon1, lat1, lon2, lat2, plon, plat, sign) { .Call(`_terra_dist2track`, lon1, lat1, lon2, lat2, plon, plat, sign) } alongTrackDistance <- function(lon1, lat1, lon2, lat2, plon, plat) { .Call(`_terra_alongTrackDistance`, lon1, lat1, lon2, lat2, plon, plat) } dist2segment <- function(plon, plat, lon1, lat1, lon2, lat2) { .Call(`_terra_dist2segment`, plon, plat, lon1, lat1, lon2, lat2) } dist2segmentPoint <- function(plon, plat, lon1, lat1, lon2, lat2, ilon, ilat) { .Call(`_terra_dist2segmentPoint`, plon, plat, lon1, lat1, lon2, lat2, ilon, ilat) } intermediate <- function(lon1, lat1, lon2, lat2, n, distance) { .Call(`_terra_intermediate`, lon1, lat1, lon2, lat2, n, distance) } terra/inst/0000755000175000017500000000000014203000616012466 5ustar nileshnileshterra/inst/tinytest/0000755000175000017500000000000014201035747014364 5ustar nileshnileshterra/inst/tinytest/test_aggregate.R0000644000175000017500000000115214201035747017473 0ustar nileshnilesh r <- rast(ncol = 4, nrow = 4, xmin=0, xmax=1, ymin=0, ymax=1) values(r) <- c(NA, 2:16) expect_equal(as.vector(values(aggregate(r, 2, mean))), c(NaN, 5.5, 11.5, 13.5)) expect_equal(as.vector(values(aggregate(r, 2, mean, na.rm=TRUE))), c(4 + 1/3, 5.5, 11.5, 13.5)) rr = c(r,r*2) expect_equal(as.vector(values(aggregate(rr, 2, mean))), c(NaN, 5.5, 11.5, 13.5, NaN, 11.0, 23.0, 27.0)) expect_equal(as.vector(values(aggregate(rr, 2, mean, na.rm=TRUE))), c(4 + 1/3, 5.5, 11.5, 13.5, 8+2/3, 11.0, 23.0, 27.0)) expect_equal(as.vector(values(aggregate(rr, 2, min, na.rm=TRUE))), c(2, 3, 9, 11, 4, 6, 18, 22)) terra/inst/tinytest/test_geom.R0000644000175000017500000000242414201035747016477 0ustar nileshnilesh r <- rast(ncol = 20, nrow = 10, xmin=-10, xmax=10, ymin=-5, ymax=6) values(r) <- ncell(r):1 r <- c(r, r/2, r*2) # compare geometries expect_equal(res(r), c(1.0, 1.1)) expect_equal(dim(r), c(10, 20, 3)) expect_equivalent(as.vector(ext(r)), c(-10, 10, -5, 6)) expect_equal(xyFromCell(r, 10), cbind(x=-0.5, y=5.45)) expect_equal(xyFromCell(r, 1), cbind(x=-9.5, y=5.45)) expect_equal(xyFromCell(r, ncell(r)), cbind(x=9.5, y=-4.45)) expect_equal(as.vector(is.na(xyFromCell(r, 0))), c(TRUE, TRUE)) expect_equal(as.vector(is.na(xyFromCell(r, ncell(r)+1))), c(TRUE, TRUE)) expect_equivalent(r[10], data.frame(cbind(191, 95.5, 382))) expect_equivalent(r[2,], data.frame(matrix(c(180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,90,89.5,89,88.5,88,87.5,87,86.5,86,85.5,85,84.5,84,83.5,83,82.5,82,81.5,81,80.5,360,358,356,354,352,350,348,346,344,342,340,338,336,334,332,330,328,326,324,322), ncol=3))) expect_equivalent(r[,2], data.frame(matrix(c(199,179,159,139,119,99,79,59,39,19,99.5,89.5,79.5,69.5,59.5,49.5,39.5,29.5,19.5,9.5,398,358,318,278,238,198,158,118,78,38), ncol=3))) expect_equivalent(r[3:4, 2:3], data.frame(matrix(c(159,158,139,138,79.5,79,69.5,69,318,316,278,276),ncol=3))) expect_equivalent(r[[1]][5,6][1], data.frame(lyr.1=115)) terra/inst/tinytest/test_extent.R0000644000175000017500000000027614201035747017062 0ustar nileshnilesh# intersection of disjoint envelopes is NULL a <- ext(c(xmin = 0, xmax = 10, ymin = 0, ymax = 10)) b <- ext(c(xmin = 100, xmax = 101, ymin = 100, ymax = 101)) expect_null(intersect(a, b))terra/inst/tinytest/test_global.R0000644000175000017500000000063314201035747017010 0ustar nileshnilesh f <- system.file("ex/elev.tif", package="terra") r <- rast(f) r[1:50,] <- NA v <- c(717627, 304.33715, 141, 432, 308.22562, 48.40079, 141, 432) f <- c("sum", "mean", "min", "max", "rms", "sd", "range") x <- unlist(sapply(f, function(s) global(r, s, na.rm=TRUE))) #terraOptions(steps=4, todisk=T) y <- unlist(sapply(f, function(s) global(r, s, na.rm=TRUE))) expect_equivalent(x,v) expect_equal(x, y) terra/inst/tinytest/test_patches.R0000644000175000017500000000173114201035747017177 0ustar nileshnilesh r <- rast(matrix(c(0,1,1,0), ncol=2)) p <- patches(r, directions = 8, zeroAsNA=TRUE) expect_equal(as.vector(values(p)), c(NaN, 1, 1, NaN)) p <- patches(r, directions = 4, zeroAsNA=TRUE) expect_equal(as.vector(values(p)), c(NaN, 1, 2, NaN)) r <- rast(matrix(c(1,0,0,1), ncol=2)) p <- patches(r, directions = 8, zeroAsNA=TRUE) expect_equal(as.vector(values(p)), c(1, NaN, NaN, 1)) p <- patches(r, directions = 4, zeroAsNA=TRUE) expect_equal(as.vector(values(p)), c(1, NaN, NaN, 2)) p <- patches(r, directions = 4, zeroAsNA=FALSE) expect_equal(as.vector(values(p)), c(1, 1, 1, 1)) r <- rast(nrows=18, ncols=36) r[1:2, 5:8] <- 11 r[7:8, 1:6] <- 12 r[5:6, 22:36] <- 13 r[15:16, 18:29] <- 14 p <- patches(r) expect_equal(as.vector(unique(values(p))), c(NaN, 1:4)) p <- patches(r, directions=8) expect_equal(as.vector(unique(values(p))), c(NaN, 1:3)) xmin(r) <- 0 p <- patches(r, directions=8) expect_equal(as.vector(unique(values(p))), c(NaN, 1:4)) terra/inst/tinytest/test_window.R0000644000175000017500000000135314201035747017057 0ustar nileshnilesh # #library(terra) # x <- rast(system.file("ex/logo.tif", package="terra")) # y <- rast(system.file("ex/logo.tif", package="terra")) * 1 # e <- ext(c(35,55,35,55)) # z <- crop(x, e) # window(x) <- e # window(y) <- e # a <- c(z, y, x) # s <- spatSample(x, 4, cell=TRUE) # expect_equal(s, spatSample(y, 3, cell=TRUE)) # expect_equal(s, spatSample(z, 3, cell=TRUE)) # expect_equal(s, spatSample(a, 3, cell=TRUE)) # expect_equal(values(x), values(y)) # expect_equal(values(x), values(z)) # xy <- 10 * cbind(-1:6, -1:6) # e1 <- extract(x, xy) # e2 <- extract(y, xy) # e3 <- extract(z, xy) # e4 <- extract(a, xy) # e <- cbind(e1, e2, e3) # expect_equal(e1, e2) # expect_equal(e1, e3) # expect_equivalent(e, e4) terra/inst/tinytest/test_raster-vector.R0000644000175000017500000000327114201035747020351 0ustar nileshnilesh#context("test-raster-vector") # #p1 <- rbind(c(-180, -20), c(-140, 55), c(10, 0), c(-140, -60), c(-180, -20)) #hole <- rbind(c(-150, -20), c(-100, -10), c(-110, 20), c(-150, -20)) #p2 <- rbind(c(-10, 0), c(140, 60), c(160, 0), c(140, -55), c(-10, 0)) #p3 <- rbind(c(-125, 0), c(0, 60), c(40, 5), c(15, -45), c(-125, 0)) #z <- rbind(cbind(object=1, part=1, p1, hole=0), # cbind(object=1, part=1, hole, hole=1), # cbind(object=2, part=1, p2, hole=0), # cbind(object=3, part=1, p3, hole=0)) #colnames(z)[3:4] <- c('x', 'y') #z <- data.frame(z) #v <- vect(z, "polygons") #vx <- as(z, "SpatialPolygons") #crs(vx) <- "+proj=longlat +datum=WGS84" # #r <- rast(ncol = 20, nrow = 10) #rx <- raster(ncol = 20, nrow = 10) #rv <- rasterize(v, r) #rvx <- rasterize(vx, rx) # #test_that("rasterize", { # expect_equivalent(values(rv), values(rvx)) #}) # #test_that("crop", { # #ex <- extent(-90,90,-60,60) # #e <- ext(-90,90,-60,60) # rc <- crop(rv, v) # rcx <- crop(rvx, vx) # expect_equivalent(values(rc), values(rcx)) #}) # # #test_that("mask", { # values(r) <- values(rx) <- 1:ncell(r) # m <- mask(r, v) # mx <- mask(rx, vx) # expect_equivalent(values(m), values(mx)) #}) # # #set.seed(0) #values(r) <- values(rx) <- runif(ncell(r)) # # #test_that("classify", { # rcl <- cbind(from=seq(0,0.9,.1), to=seq(0.1,1,.1), becomes=1:10) # rc <- classify(r, rcl) # rcx <- reclassify(rx, rcl) # expect_equivalent(values(rc), values(rcx)) #}) # # #test_that("app", { # s <- c(r, log(r), sqrt(r)) # sx <- stack(rx, log(rx), sqrt(rx)) # rd <- app(s, mean) # rdx <- calc(sx, mean) # expect_equivalent(values(rd), values(rdx), tolerance=0.00001) #}) # #terra/inst/tinytest/test_extract.R0000644000175000017500000000522014201035747017217 0ustar nileshnilesh f <- system.file("ex/lux.shp", package="terra") y <- vect(f) y <- y[1:2,] x <- rast(y, res=.2) values(x) <- 1:ncell(x) expect_equal(cells(x, y), cbind(ID=c(1,2), cell=c(1,4))) expect_equal(as.vector(cells(x, y, weights=TRUE)), c(1, 1, 1, 2, 2, 2, 1, 2, 4, 2, 3, 4, 0.68, 0.55, 0.1, 0.01, 0.13, 0.67)) expect_equivalent(unlist(extract(x, y)), c(1,2,1,4)) expect_equivalent(unlist(extract(x, y, cells=TRUE, weights=TRUE)), c(1, 1, 1, 2, 2, 2, 1, 2, 4, 2, 3, 4, 1, 2, 4, 2, 3, 4, 0.68, 0.55, 0.1, 0.01, 0.13, 0.67)) r <- rast(nrows=5, ncols=5, xmin=0, xmax=1, ymin=0, ymax=1, names="test") r[c(2,7)] <- c(15, 20) rr <- c(r, r/2) names(rr)[2] <- "half" xy <- cbind(x=0.3, y=c(0.9, 0.7)) v <- vect(xy) e <- extract(r, v) expect_equal(e, data.frame(ID=1:2, test=c(15,20))) ee <- extract(rr, v) expect_equal(ee, data.frame(ID=1:2, test=c(15,20), half=c(7.5, 10))) e <- extract(r, v, cell=TRUE) expect_equal(e, data.frame(ID=1:2, test=c(15,20), cell=c(2,7))) ee <- extract(rr, v, cell=TRUE) expect_equal(ee, data.frame(ID=1:2, test=c(15,20), half=c(7.5, 10), cell=c(2,7))) ee <- extract(rr, v, cell=TRUE, xy=TRUE) expect_equal(ee, data.frame(ID=1:2, test=c(15,20), half=c(7.5, 10), cell=c(2,7), xy)) ee <- extract(rr, v, xy=TRUE) expect_equal(ee, data.frame(ID=1:2, test=c(15,20), half=c(7.5, 10), xy)) f <- system.file("ex/meuse.tif", package="terra") r <- rast(f) xy <- cbind(179000, 330000) xy <- rbind(xy-100, xy, xy+1000) e <- extract(r, xy) expect_equal(e[,1] , c(378, 251, 208)) e <- extract(r, xy, method="bilinear") expect_equal(e[,1] , c(378.00, 270.75, 197.25)) e <- extract(r, xy, method="bilinear", cells=T, xy=T) expect_equal(unlist(e, use.names=FALSE), c(378.00, 270.75, 197.25,8173.00,8016.00,6041.00,178900.00, 179000.00, 180000.00, 329900.00, 330000.00, 331000.00)) r <- rast(nrows = 10, ncols = 10, nlyrs = 1, vals = 1:100, names = "temp") x1 <- rbind(c(-145,-10), c(-145,-5), c(-140, -5), c(-140,-10)) x2 <- rbind(c(-10,0), c(140,60), c(160,0), c(140,-55)) z <- rbind(cbind(object=1, part=1, x1, hole=0), cbind(object=3, part=1, x2, hole=0)) colnames(z)[3:4] <- c('x', 'y') p <- vect(z, "polygons") rr <- c(r, r*2) test <- terra::extract(r, p, fun = mean) expect_equal(as.vector(as.matrix(test)), c(1,2,51.5,53)) test <- terra::extract(rr, p, fun = mean) expect_equal(as.vector(as.matrix(test)), c(1,2,51.5,53,103,106)) test <- terra::extract(r, p, fun = mean, exact=TRUE) expect_equal(round(as.vector(as.matrix(test)),5), c(1,2, 51.80006, 52.21312)) test <- terra::extract(rr, p, fun = mean, exact=TRUE) expect_equal(round(as.vector(as.matrix(test)),5), c(1,2, 51.80006, 52.21312, 103.60012, 104.42623)) terra/inst/tinytest/test_focal.R0000644000175000017500000000363714201035747016643 0ustar nileshnilesh m <- matrix(0,3,3) m[c(4,6)] <- c(1,-1) r <- rast(nrows=3, ncols=3, vals=1:9, crs="+proj=merc") f <- focal(r, m, na.rm=TRUE) e <- c(-4, -5, -6, -6, -6, -6, 4, 5, 6) expect_equal(e, as.vector(values(f))) f <- focal(r, t(m), na.rm=TRUE) e <- c(-2, -2, 2, -5, -2, 5, -8, -2, 8) expect_equal(e, as.vector(values(f))) expect_error(focal(r, m, fun=mean, na.rm=TRUE), pattern="[focal]") #e <- c(-4, -5, -6, -3, -3, -3, 4, 5, 6) #expect_equal(e, as.vector(values(f))) m <- matrix(1,3,3) f <- focal(r, m, na.rm=TRUE) e <- c(12,21,16,27,45,33,24,39,28) expect_equal(e, as.vector(values(f))) f <- focal(r, 3, na.rm=TRUE) expect_equal(e, as.vector(values(f))) f <- focal(r, m, na.rm=FALSE, fillvalue=0) expect_equal(e, as.vector(values(f))) f <- focal(r, m, na.rm=FALSE) e <- c(NA, NA, NA, NA, 45, NA, NA, NA, NA) expect_equal(e, as.vector(values(f))) f <- focal(r, 3, na.rm=FALSE) expect_equal(e, as.vector(values(f))) r <- rast(nrow=3, ncol=3) values(r) <- 1:ncell(r) rr <- rast(nrow=3, ncol=3, xmin=0) values(rr) <- 1:ncell(rr) f <- focalValues(r)[1,] e <- c(NA, NA, NA, 3, 1, 2, 6, 4, 5) expect_equal(e, f) f <- focalValues(rr)[1,] e <- c(NA, NA, NA, NA, 1, 2, NA, 4, 5) expect_equal(e, f) f <- as.vector(values(focal(rr, 3, max, na.rm=TRUE))) e <- c(5, 6, 6, 8, 9, 9, 8, 9, 9) expect_equal(e, f) f <- as.vector(values(focal(r, 3, max, na.rm=TRUE))) e <- c(6, 6, 6, 9, 9, 9, 9, 9, 9) expect_equal(e, f) f <- as.vector(values(focal(rr, 3, sum, na.rm=TRUE))) e <- c(12, 21, 16, 27, 45, 33, 24, 39, 28) expect_equal(e, f) f <- as.vector(values(focal(r, 3, sum, na.rm=TRUE))) e <- c(21, 21, 21, 45, 45, 45, 39, 39, 39) expect_equal(e, f) f <- as.vector(values(focal(rr, 3, mean, na.rm=FALSE))) e <- c(NA, NA, NA, NA, 5, NA, NA, NA, NA) expect_equal(e, f) f <- as.vector(values(focal(r, 3, mean, na.rm=FALSE))) e <- c(NA, NA, NA, 5, 5, 5, NA, NA, NA) expect_equal(e, f) terra/inst/tinytest/test_vector-subset.R0000644000175000017500000000062114201035747020352 0ustar nileshnilesh f <- system.file("ex/lux.shp", package="terra") lux <- vect(f) expect_equal(dim(lux), c(12,6)) expect_equivalent(unlist(lux[,"ID_2",drop=TRUE]), c(1:7, 12, 8:11)) x <- lux[lux$NAME_1 == "Luxembourg", 2:3] expect_equal(length(x), 4) expect_equal(nrow(x), 4) expect_equal(ncol(x), 2) expect_equal(unique(x$NAME_1), "Luxembourg") expect_equivalent(unlist(x[,2,drop=TRUE]), 8:11) terra/inst/tinytest/test_crds.R0000644000175000017500000000021014201035747016472 0ustar nileshnilesh m <- matrix(c(0,1,0,0,0,1), ncol=2) v <- vect(m, type="polygons") x <- as.vector(crds(v)) expect_equal(x, c(0,1,0,0,0,0,1,0)) terra/inst/tinytest/tinytest.R0000644000175000017500000000013314201035747016367 0ustar nileshnilesh if ( requireNamespace("tinytest", quietly=TRUE) ){ tinytest::test_package("terra") } terra/inst/tinytest/test_matrix-input.R0000644000175000017500000000347214201035747020215 0ustar nileshnilesh expect_equal(class(rast(volcano))[1], "SpatRaster") ## degeneracies dm1 <- rast(matrix(1:10)) dm2 <- rast(matrix(1:10, nrow = 1)) expect_equal(class(dm1)[1], "SpatRaster") expect_equal(class(dm2)[1], "SpatRaster") expect_equal(dim(dm1), c(10L, 1L, 1L)) expect_equal(dim(dm2), c(1L, 10L, 1L)) r <- rast(matrix(1)) expect_equal(class(r)[1], "SpatRaster") expect_error(rast(matrix(1:4)[0, , drop = FALSE])) # test_that matrix input type xyz works r <- rast(cbind(as.matrix(expand.grid(1:3, 1:4)), 1:12), type = "xyz") expect_equal(class(r)[1], "SpatRaster") m <- cbind(x=c(1,1,2,2), y=c(1,2,1,2), z1=1:4, z2=5:8) r <- rast(m, type="xyz") expect_equal(as.vector(values(r)), c(2,4,1,3,6,8,5,7)) #---------------------------------------------------------------- ## ensure matrix and array input result in extent 0,nrow,0,ncol ## no input r <- rast(ncol = 4, nrow = 4, xmin=0, xmax=1, ymin=0, ymax=1) expect_equal(c(xmin(r), xmax(r), ymin(r), ymax(r)), c(0, 1, 0, 1)) ## matrix r <- rast(matrix(1:12, 3)) expect_equal(c(xmin(r), xmax(r), ymin(r), ymax(r)), c(0, 4, 0, 3)) ## array (degenerate) r <- rast(array(1:12, c(3, 4))) expect_equal(c(xmin(r), xmax(r), ymin(r), ymax(r)), c(0, 4, 0, 3)) ## array r <- rast(array(1:24, c(3, 4, 2))) expect_equal(c(xmin(r), xmax(r), ymin(r), ymax(r)), c(0, 4, 0, 3)) ## unless we provide on creation r <- rast(matrix(1:12, 3), extent = c(-2, 10, -1, 20)) expect_equal(c(xmin(r), xmax(r), ymin(r), ymax(r)), c(-2, 10, -1, 20)) r <- rast(array(1:12, c(3, 4)), extent = c(-2, 10, -1, 20)) expect_equal(c(xmin(r), xmax(r), ymin(r), ymax(r)), c(-2, 10, -1, 20)) r <- rast(array(1:24, c(3, 4, 2)), extent = c(-2, 10, -1, 20)) expect_equal(c(xmin(r), xmax(r), ymin(r), ymax(r)), c(-2, 10, -1, 20)) #---------------------------------------------------------------- terra/inst/tinytest/test_cats.R0000644000175000017500000000113614201035747016501 0ustar nileshnilesh set.seed(0) r <- rast(nrows=10, ncols=10) values(r) <- sample(3, ncell(r), replace=TRUE) - 1 lv <- c("forest", "water", "urban") levels(r) <- lv names(r) <- "land cover" v <- cats(r)[[1]] #coltab(r) <- rainbow(4) expect_equal(v$value, 0:2) expect_equal(v$category, lv) ftmp <- tempfile(fileext = ".tif") z <- writeRaster(r, ftmp, overwrite=TRUE) v <- cats(z)[[1]] expect_equal(v$value, 0:2) expect_equal(v$`land cover`, lv) levels(r) = cats(r)[[1]][2:3,] zz = writeRaster(r, ftmp, overwrite=TRUE) v <- cats(zz)[[1]] expect_equal(v$value, 1:2) expect_equal(v$category, lv[-1]) terra/inst/tinytest/test_classify.R0000644000175000017500000000145614201035747017371 0ustar nileshnilesh r <- rast(ncols=3, nrows=3) set.seed(68) values(r) <- runif(ncell(r)) # from example # all values > 0 and <= 0.25 become 1, etc. m <- c(0, 0.25, 1, 0.25, 0.5, 2, 0.5, 1, 3) # from example rclmat <- matrix(m, ncol=3, byrow=TRUE) rc <- classify(r, rclmat, include.lowest=TRUE) expect_equal(as.vector(values(rc)), c(3, 3, 2, 3, 2, 3, 3, 1, 2)) values(r) <- (1:ncell(r))-1 m <- c(0, 2, 1, 2, 3, 2, 3, 8, 3) rclmat <- matrix(m, ncol=3, byrow=TRUE) rc <- classify(r, rclmat, right=FALSE) expect_equal(as.vector(values(rc)), c(1, 1, 2, 3, 3, 3, 3, 3, 8)) rc <- classify(r, rclmat, right=TRUE) expect_equal(as.vector(values(rc)), c(0, 1, 1, 2, 3, 3, 3, 3, 3)) rc <- classify(r, rclmat, right=TRUE, include.lowest=TRUE) expect_equal(as.vector(values(rc)), c(1, 1, 1, 2, 3, 3, 3, 3, 3)) terra/inst/ex/0000755000175000017500000000000014201035747013115 5ustar nileshnileshterra/inst/ex/countries.rds0000644000175000017500000002135114201035747015644 0ustar nileshnilesh}oؖϖdGWwUwUef0/SK^&HP%⇊7fE7%U ,d @"@l+/%Q3Ew]{>~CoϤ-WSdk볭]j(ğ] qp&+"ka쏃ٮq8wˀz\qxe׿һ{pǧcz0f O/d7/x({A(1Sz)<2-dr惊h č'~=SO,e08')o봄o`DzFCp2C-qBn(Y0H%Q }Z/b?f.K?]hDܜNyN0;S^37?zxRCKf^ wRG"!.&q]0QFjh p'"Ւ6mUx:)1zaEqg"eߢO~ ~b?>evBDl}FY5h<Ye5+x/ Ǔ+$ߒ.-h6.xc"}$SZ!~`/9w@Vpt-Zބ_}/~K66w) Oy x.9!w.e.Q1E͂",H(Ik]59j݄Y<6Ofι>L!#]fLFpNdpA ;.yd*B 3ON|].߇D} >P8>ίw>Pq|aXAJ箈y>tCa>kJ hL8.qspp-IIį "EgGN 2yK8j.60_߲GיT"`$fON{np}z P-G WTr ¶zzͻSya8^6`z(&im˞Ʋ^r Ȧ=9ᙟ(ꑶg4Z >ޛ&MpB<!k-T{oE㷳tD?bٞ 1ڋ'+~{5]oIcþȗH7p:ˑ)2\}04d,w_}J|? Cվ?A!90Qd<2Ld _)ohLд_" aJĀ.p UaT:(zJs\s\B&f(`v^'|WJf ͖idu4M1t`^Z妇17t4571B74ۙ&4Lnr_M8Gb%TnijŽ`*7j-q{6zWpdʺꮎu `j9e2uur]bAK^+0;67Y{'WA esr[]nb{aUMpwݺ.DzLNwɔ2 T OqrylҞ=u]{L}&> # #3 <&`I9D hih9hhh&y<[ ZZIuRlp#A_shzbb :8&h1-XG8RYRU@).:%PANR^\7@u [TnA 40Y4@JjX$ @n#iM`KIMMd`R s@U 0[ K-"oIˤŠZPIp1r;EǼ:E-3 h&XzI#WAKpw@)`\%V ٫dA\GI,X5s LQ`e&k5A /wMpqdbm&dL^2IB)!|$ļE&Yஅ9,#K(@=B tA  Z)'?w.CP+uY@J ])IH%D˒ `H$pr0RyPqd BX!㩓B !5\pޅLXKn* nAE\p=FLB5BF"<adԗ${xP(A.(H HHE2*>}0 ԇfB!R~pfYJXpNj+z*ղ5]>[CRQQ\Z AY=!+R5SwN}WqZX15GWKvN)8#u,-vkk%{)z,+Ns=G12+7tXs~.U=g0[kFKi imKm[Њ)!a<1; r-CipIV-i֕VR1]]t*˱ֲ' E br΃+tIyWۆ9#2 >+ ;:qMU z:n72e{_8$4Yi&h^@mB\Uەh9 ~ 93ߎ֑ H=Mn䯩BUmBɐeL[%U)MËΩݙچmYm*]Mk"=Zȶv_U{"{R<ʑIRQc o)b Uk$SMk -,SAAP ihdfHRZGpU9Ps= .iflz،=5kv'kV9M_7F[S1KtKM86?3uձ-Օ}54LRR=+G. NW]ԉwZ:٬![AfC3JKh⣤r uOKr4 \UFw,winO3G31ydڏ2KkYqoښB6yV7d#p$_M[ѡv"DN 1ZnviUw%۪&dX QkJ+5UVtQK)H<.+jS9@*^G9V:LѬ#(Qig ̄ZGw~y>R/;6~+ޡtT6[jv^E(¦^πtIJ/?m"K{jT6 C'H4::cԵv{(jшG=\1=펙A Ù*@WLhB&d-U 5G,U17:zBӺm0_ZC j6v|kԯ_43{W$ <{BU3e;I$h`E(1XW]a-XѮKBLb8ɳa b.]괒 0Gd_} :s|?|(֞(02lThk3ݞ$֌QյL֖7 a]1xya3` زg]R\xl6H;u&$="AbuOX=089£1da"w[m+0XFQ(P)z΄DzϼlhןRm %Ϯ7WUT"F`*3)xH`i<9QtL],".ȦfțS;{mmSa;2)qD2_ Lܫ)3{u-?iȮ4U;J^KӄY`F75$P.ivLJ taZrU 4i|e 0Uy{)yO"\pr#+}E~#+4eNt݋ja Zܟc~v&/zn([˶0>[**^=?,*BJ#ÇSleBӚD%k)Io)ōg]Irc-ϲIvP}s}%j< FooN!z&EVk0~RIeTdr@^1f8J>Ec YFWD'MDr:ô>'~NP.ez,x:l ^3Su[EQۗ|GcAJ6{"m§e6I $՛كϵ`Eˢ <WM4zNRIबIYYrrF\Sk:<4sZ>ДJuGd%޹όJzb\S$M)4GdK*갬Y]/>vEhk2Ղ& F3"/&gUI#P_O`D ]&$.E 잊@4l0@2sՠgJı%2ZAIzܸߧ#7?GI^di/wV [ (5e Rz攠dzJS8[$Th0\Pg(bjWjMEY)<GaIGRočlMiMN~ Vrc\ɦc#ٝL2J[SF< $ JWa,0m½o͏XUMR)q2R}tW=9rӹvS.`}# X3idKL V  3Ix^wtL+]JHr_=ī&*\ל(ySfrVE8hh!_X4?l&:OFJ(%`7}6':mfOfu35_Qն%?t*XhJR!cBZ"OIP} BIoEb׳ ~\PjV^ ,)lD*,T%AQqP{q\Ej est+" u9O 5ǀS"WffD%~_D`%|k8-G@iV;=`/>ewDe`pB?#?̕~5U_uy.nR)] _礔=_}N?ŪDsb%6BnBvفҿ+d_[Vi>٧Dҋ}φ ,gA* [?EULpg>hW%<9 u7E A~W$umG01b$;ly/Ċ:;h KBy#B޴LeU>fmqBYat. X$N9*99=V _N{5e~J̳H˗bAVaFqswH{AVoJ*6ŭ pKS2,&w"^\]2bP]( s XbY\&KP*.-HX< /Q¾EfA鰠H uCQ^ԑEp-"哬2WŪP×&HVh9%GTW[lbt^.e1{) $XF, @*vź4i/I #TPEYY9E-.FH B+K j($=` +\puE, Mi(DUȺB/ZZ?E T9BEC(Y,匲gTV2+bKP\d|NP߰x#{. WHjv7_ 48=+9W]e\5_uSc}!s~O_ɫ{R=7{z,]۫V2e9kU9)j7VEoOua]\yUu^1-e'Nc+M.8Qm[:Rd][I71j̕vB6wUJrV>܌oe1wL%('Kb}eUb]$SKqwnSh}ۨWR@+ I/nw &W[/[FIo^"*ʧy!% !yKqJ 2Bo6m,QJtn\JHi96T['%ZbپVn}Z6 -◓`dy.mNӱu~[7$^׍`6.}SC[Fooމko{NnPJW CC` vFW]`}3,ny7Oo/K2\M |JQ-%cPK:oK["wNTi>VۺkeW:qrܛ^bv_s4?xճo쪶К͓}:G)ͽ3V4}7>]#OGM*terra/inst/ex/meuse.rds0000644000175000017500000001263414201035747014753 0ustar nileshnilesh[ tTU #D@ T%yHjJ2 !̨@@L*6Ђנ6ߦF4(*( HdP *3{ߗz~*s9R7 mX-A}R_^+h\KZcHt,ش p=vcK.a/KW%1묑@baoX171%8"[$#h#OlO")zDܡ$ւڈ&bP̃Q  ioIz8 ?B[ȿZ~-~)󰞄IY71YoQZ/6Cu~>~ۇxw|-C>2bߛ  ~˱Zo+K1O ò "PgaW=DH B/!i U q_xQSV<B}9 Kg`c^GXD?ngoc?!q}|@>C]*KsO8qZ|_ywI$DO?8d}-qJ>z9nBb{o5v¼;#4Y>M%.K۫AyA@[Ov6{ n" ԫsN=m:JȳNQ!J(52|聽}H¾'acl%Jl9ꔈkui / >I{ktأ?Za[!6"Rbsԫ-Ꝉa~ DEؿ4^No2x;_v\C߶yGK~ /M\`[%< #-'c?ݘ}[ek`Sĝ/Cbe:P8`sY ʍux?rQ~"j`ae#2YH`ID>_|'>g.i[%NGE@<ِ>|A9g`7}`>>~˴yy?q]곿E`||_ycL.8䟼7 s_Wy0ø>zfqN܇LHʐ y~`{k|-%;%ΡV<;A|%z>֗ Y/|1^  $έ>C>y|9X#N؍|,/BߗX. C^OD[%N慸̐o$BoF }C+i/F~|>Y|}z]My~=WscEWsm-b[^$HF5OQub#gczgфqE!(!=oDgC|Iy,7װ[Wc +mAR%~ц3/}jU/k"vvN ]Ѻao 6[k?p{%o\쓸D}~EvW|=2-yZa~NzKݕ_qw<Ǔ7mucGNoU"yơ~bOAS_o򊳏o kM6?V{%|Y?m~9$+mwZdY=lF{oՄiIyڎ-dBjW\^?T{_+nU,nij@G{9X+V[㳯}Au!\i{M-YrV9'ӟ}roUh-ځ.WVz}gnrm[VNO}tX{Ul~F^T=Y< :Zźq}[[+V>yĩ:Q&ګ [r\{Іke ^= )І N~B;rǓMvْ-[п⛬hewnjQG#}^~em[_]_=ckGWrԻvx'^H.Կ\{A}+Wʴw^đmC|?J!T?issvn~k/,}qmK#5>#hiVOֶڳEkш^㪏M]aڞ}Ds'au'u~ΤU;>گ}SΎXYvdGiK/Nv3S;yrL-muvҳ>v8oQ\vxŜ9kg[G&]<;4q:sυ;jzzֽ<}"tvEh/W;ꫭQdwZ*,]wx[BuOx{kpGgbHiGyPx4=)9֎g~Ľ7;z^S[]ާmP뻆aIjX]އ>]\w,+ yIX7:`u~w:tƲ>{BjqR|>}zfeT+5tޫ8y9「~vA/=bko ?M;=~o龭 g{b>Iޔ?og|(pnE$2zׇyOfK,E}XOӽ%?w^o=o[YVvo^8/r޳70߇y{ccw^C cY+%?:?=2)=)?o䍀6#س^\-ynޓ7Gb: y)zߴoDG"/4kOぬYsY,!7_A]__!WhF0k䍜<2o>JiPN\&Ckv^$)o2 ѕk9Oj-}{ {]f/Uc#vO`^m\>Íj|=_Ww4dE h`kɿoCn2!k:>!SnWc+Ĥ\M5"TV+j1^euMWizVׯ_«3jc2i3r~\E탮k~9Wa=o+dQV1j4 ޕS0 ޣ/=EO.FpPLCo/%8y78$o$ aǿ@:o/!79߇2EX`[% 3 fs 5ż E@wBΛ{A|s@k!_<'ry=@"ȿR!'@{'zvo"d&cxȃ}s>9`ǿ@ީeه -s̓ua~w?utyp?njq_8`;|)@?̇qrx_ y17!sHWbP3;3g|n15 Fb723i9jqN">:jTȉT\I 9œ8n))z1psA2)2D5JR#ȭF5Qp*p*p*p*p*p)p)p)p).٥<@2I@`=`=@`'I@1ܱH@@I@xfO@;I@<@R@mI@}g@G' I@$Bm@[I@Q{@bOI@P6@U I@LA ^@(TI@8> @BI@b;@}@"`I@Q{@Ju {I@Hw@I@ؿ%w@\_I@06}@gieI@ D @j/I@}\ @I@?4@V4I@@?I@C`8y@0I@f$!z@y MI@XZ㿂@OI@?mz@( I@؟z@0 \ I@_ @p^ I@_l@ I@'t@D I@<t@S@h I@L8{@`? I@n@o I@Zp@* I@ ߤi@ I@źi@ I@1p@I I@=Zp@2_ I@&tv@j I@}w@3 I@_p@nI@o&q@d_SI@Aq@t}(I@_j@&I@@j@j5HI@%? f@;^I@sZd@`CI@R d@I@ؘpk@5I@) #k@<I@#q@|`I@/%?;r@ߞI@ sr@1GI@\ (y@wI@5 ty@ XI@m7)@J2I@Wy@ HI@%_[z@{I@?_@I@B_Ň@`I@n_@N|I@QI@ I@ 1@KI@)@{@ 0 I@@ _!I@?d@#I@@`I@D @U 0I@;@OdH@)wu@?H@U ă@H@?n@Ym_H@%@l@H@?h@o H@~ܟf@@AH@Rï?&a@,dH@N_@6H@3^@H@?[@ H@zZ@7H@|NQ`X@ yH@,W@~fH@o?T@OH@T"S@Y:H@YNQ@TH@q˿P@;H@<@N@+H@ * `5L@G~RH@VMJ J@`H@-#`G@f H@,_AF@h?UH@ wC@zH@r@@QH@ǻ*9@P KH@P@E7@DH@5@\3H@1Y4@z`H@rER3@Y H@LY3@HH@JV3@3H@p?3@?H@)3@H@D3@X @H@2@IqH@L_T2@ecH@@0@> @LH@Z/@g9H@˲P+@@H@5=*@H@?)@H@ 2)@=jH@O_(@U `H@\*s(@?H@<:'@_H@_%@H@M $@_H@/ן!@M#H@j@HH@vs@qhH@@3H@>C@S?H@ @X@H@J@eZH@a@z`EH@#@fqH@;}@tH@r@H@A7 @&`H@k-#@KqH@7`O'@PH@5)@/`jH@= *@x}H@,@_H@|`1@,H@3@H@G,6@H@-7@H@g_*9@_H@_D?^:@7,H@,?:@&@@H@ 2;@~ UH@J;@$H@;@H@#;@b`H@;`&;@\I@w?8@ ~I@wP`l7@?I@J 5@ޚ I@3@@I@0#@v0@ I@f.@|ߥI@&@u)@I@܋&@ @iI@3#@F II@&H*@I@Y@I@YNj@# I@|v@NI@S @'I@S @9C?I@*Ʒ~@?]I@?@]I@?@$ I@o$߄ @PI@K @5I@ؿ @6"I@GR@cv3I@п@;R <I@@JI@@@AxI@з?@KqI@@I@{&@;?I@U@ I@(@&`AI@҂d@*hI@vI N@0I@?@2I@| f@ TI@?@I@@4_I@@@mI@:@o 1I@ì@V `NI@M0@1eI@?M@.nI@쿭?@I@ɿ@@I@M@ɠ`vI@__@G' ]I@CH@2I@z ,@k_I@l@I@җ+@7I@ V@@?jI@0@/e HI@_@k_;I@@8I@0@0 9I@+3@@BI@Z@O۹@oKI@Ű?`@?bI@:Q@I@1@WI@?a@ I@F*ԯ@KI@@@I@_@WI@dޫ@J`I@؟@nI@|X@ I@O`@mI@ٟ8@bLI@)֪@,)I@R@pI@A͟@/"I@! z@|cI@@^_kI@@ZI@%@0 9I@_i@I@yo5@tI@ Ү@I@g'ſ@,nI@٬@ ~I@M:4@9+lI@ߩ@= ZI@"4@q@`4I@jqި@.I@K@fB_I@ `@2pI@J@^I@)@S.I@W@o$I@@W`H@Y߿@H@G@H@Ia @FH@}@v@H@a_@H{H@@&@@H@1@cv3H@x1 @%0H@MK݃@V4H@@ŭCH@~f|@3 H@{@B?H@9Wޟz@oc?H@k[9 y@dH@Ax@ngH@:]w@tH@&4eu@wPH@IQ`Ct@x1 9H@>\0Wo@+H@C@Sm@H@]?)k@$t`H@Yh@lH@7@^@pH@MT%Q\@H@/[@H@Β:>W@lKH@K O@ H@}˿N@>dI@p<N@aS`I@"bO@;_I@U@2I@& b@ـI@k@,I@{PUr@I@=p@4TI@bo@ө I@XE, o@ I@`kt@@)I@,@5u I@J_*@u I@8ߡ@s I@:? +@\! I@# @@(@ I@<"@.}  I@\M?@ I@Q@ L I@"Nx@ I@j @ I@*s@ I@0@U>I@[?@->xI@5@_)I@Nz@fB_I@ ` @U>I@}7@@kI@ @oI@<`@q?wI@͓@6uI@y.K@F?I@.@,nI@?@ڿ_?I@'@@l I@ C@ tH@1 ZC@,dH@uv@ ;H@. @_mH@ٟ@H@^>@@H@yD@=?H@I6@YH@W_@^;H@__/@ bH@۽?R@H@_@_H@ V9@r@?H@ߖ@WJ H@Զ@JJ5H@|5@?@H@@*hH@6  @N%@H@" @LYH@ jӿ@H@o?@N=_H@@_H@c+`@IH@' X@ڧ@H@u@H@s@H@L@N@:H@|M@;R @CwH@@MH@ ?1@`H@B v@\9H@/,@d^`H@_ @cH@?o@{H@(E@0H@@sH@t@ H@@2$@H@C@)%@H@<+*@H@?0@$H@(f9%6@.H@JG_<@@l H@/ =@~G`DH@6@:H@)8S7@sH@D_`p=@oH@?=@0aQH@1 ZC@L`H@}C@,H@I A@nH@״@@@KH@U@-@@ ;H@I>@ H@HF=@wI? H@vu;<@_H@K:@@H@(6@AH@=)@Z_ H@/"/%@H@pI "@# H@^ɟ @Y $H@!@QH@C@u& 3H@P@?H@8E4@F H@&S`\@\!H@~@ bH@<@>H@B@'H@84`@Ǽ H@i@NH@Զ @FH@  @(H@ @k\ H@ @(H@@ @Ym_H@-$`t @OH@?@H@ O@_H@EDֿ@_lH@5`@CH@RGr@0H@=@_H@ ` @P H@. @AQH@ @/"/H@ٮT@o@H@aN@hH@^9 @`YH@k@T~`9H@X?{@H@K H@$t`H@Lv@:H@& @ɠ`vH@@V `NH@ZT8@8@@H@K @ H@@BH@W=@ tH@9@@cwH@t@ H@hbb@n @H@º_@ jH@zŸ@l?H@*&@ߢH@k=@&@H@@DsH@M`@h@H@*@_H@5@6 @H@% @VH@do0@H@y_@@ZH@#%6@:H@j,@_@H@m w@H@n{_z@_H@-$`t@)c_H@'_n@ H@mo@\H@߃@:H@D1@H@@H@>;@7H@_v@_H@% @tH@ܟ@7H@z?@kH@ս_@ZH@n{_z@ H@ @V4H@U@=uߔH@K@e@=?H@mJ`@ eH@_)@(H@$ÿB@r/H@C N@+H@`@j H@ O@0sH@ޛ׿@ 1H@ɿ@kH@۟@?H@'D@G`H@>;@6"H@XC@>H@#N@v@w@_H@+෥@ oH@@ H@˷_@H@I7?Ý@(@H@ +&@0 H@@@ `H@,@n(`{H@! @Ym_uH@? @b`nH@(?@҂dH@ם՟P@YH@ZR y@* QH@V'@@:H@ @H@˄@^H@1 @. H@@@) @7 H@O @mgH@}@J`@H@1Y|@11 @+H@?z@WJ H@a u@`, H@ s@H@S?r@>EH@ 3o@?H@#Ol@*H@DE j@H@lf@"MH@'c@`(H@H"c@?2H@3@.`H@ؿ<@?bH@ ;@@@`H@Xߟ9@UH@X8@DsLH@;n7@s_7H@'?53@ H@(U2@@@H@R0@2pH@/@eH@S?.@y-H@G@,@¢@H@ )@WH@PK9&@. H@_."@2H@2G@2_H@H@Y߿H@@_H@2.ɿ@OH@qߗ@@H@ @H@~ @vH@l@H@&@:vH@1O@o ?H@D@!H@h͟@@?H@F+S@lH@nAL@H@82n@,H@`)ß~@H@wؿ@ `H@@5H@ I @7H@ןH @wH@C@_H@_@aH@[@H@l@4_H@҂d@ H@@X@H@*@qr`H@_@k\ H@@+?ZH@/"@H@߈@`H@ٟ8@H@Ag@y-BH@٬@h@WH@/ @jt?kH@5M@ 0H@A@@H@@@ө H@@4_H@,@@bH@L@?9H@$@ueUH@aR:`p@H@#;@-VH@  @Ǒ?H@4@cH@}@.H@]a@_BH@:P@WH@xE@/ H@C@lXH@G' @s@H@&@cH@Kڿx@!H@K$@n@._H@` @PH@?@qH@z @?H@cv@~H@b@ H@@>@%`H@G@_H@G?@?,H@>@2-4H@r/@r?H@'͟>@> @LH@b0@AQH@@ecH@zk&{@~H@$`@CwH@A_ @`?H@lݟ @H@_Q @`5H@f @ @HH@ @?oH@ @_H@韷@WH@r@g*@CH@z^@AiH@{9?2@?H@ff@aH@D@=H@_?@aTH@_@q yH@~_@% H@@\#H@Y$@ ?MH@?~@W`aH@N.l@@H@V@Y H@$s4`@&`H@O\,@_WH@M,@YH@R,@H@+@v H@N@)@> @LH@mo)@H@WJ )@H@դ%)@V `H@FW_*@2H@˲P+@@H@Z/@g9H@@0@> @LH@L_T2@ecH@2@IqH@D3@X @H@)3@H@p?3@?H@JV3@3H@LY3@HH@rER3@Y H@1Y4@z`H@5@\3H@P@E7@DH@ǻ*9@P KH@r@@QH@ wC@zH@,_AF@h?UH@-#`G@f H@VMJ J@`H@ * `5L@G~RH@<@N@+H@q˿P@;H@YNQ@TH@T"S@Y:H@o?T@OH@,W@~fH@|NQ`X@ yH@zZ@7H@?[@ H@3^@H@N_@6H@Rï?&a@,dH@~ܟf@@AH@?h@o H@Oi@)2H@&_h@H@mh@tH@p֟Hh@v %H@Z}g@H@gߞe@bH@`d@LA ^H@>Ad@fB_H@rc@6_H@z)Lc@sOH@P@b@1 H@;`@bH@`@?H@O_@?oH@Od7_@ H@ka@k?H@E Eb@v@H@ub@E|H@0I`~c@͓(H@4_c@$H@߽g@ @HH@h@]`'H@<%R`"j@wI? H@+ j@_H@8l@>EH@+ Vo@va_H@?p@߱H@Dr*cq@;H@q@7H@2){q@sH@n&p@G:H@p@y*H@5p@`H@ @'q@u H@<_q@@H@4 r@OH@! zt@;_H@u@H@DHv@lH@w@H@;`Gy@tH@I }@baH@A@?UH@;@?AH@ ۪k@K'H@OM΃@N| H@%@H@I@І@BH@$@Y H@u@4<0H@쟆@ @H@"@6_H@_ @5H@ ` @S@H@3@H@p?ܗ@~ H@&4e@{<H@7T @?_H@T;`@.:?H@g*@Ü@lKH@ @_)H@@`, H@'j@bH@:~@6 @H@9@͡@H@ߣ@#H@"d(@w@H@)NAR@-@H@v @H@8Z @(H@ҫ-@*hH@Y@ 8H@3@nH@vu;@11 @H@@]H@uv@ ;H@ &k`@H@J?@@H@5;@ԑ aH@ËՆ@7H@)!@6H@@;H@  @>]AH@PvL@@2TH@/ @q@b`nH@! @H@)^@4 H@@H@Ӂ0@ H@V@;H@9Qח@&@@H@;B@:@s@H@G?Ҙ@J'H@R0@Ro?=H@i@ H`H@ o@H@ÿ@0 \H@0r@+7H@ @\#H@ @_H@ @->xH@Gؿ@INH@q_S@58_:H@W@@&H@H:Ϣ@H@A@u@+rH@-Jb@QHmH@q @~G`DH@5@'@y@H@$qP@Y H@@Ǽ @H@6٨@g+H@?D8@qH@L?@fH@J_*@H@BӲ@\!H@B@zTH@ε@y'H@/y$@_BH@&@jH@ʋL@JH@VN@?H@U @[H@!c@"kH@B1@HH@"P?@ H@t@H@ "@]@H@'@6H@=@+rH@PS{@H@@l =@@H@ԟ@_mH@J @G~RH@w @v@%H@O@ZU@H@N@LH@,@@bH@@4_H@@@ө H@A@@H@5M@ 0H@/ @jt?kH@٬@h@WH@Ag@y-BH@ٟ8@H@߈@`H@/"@H@@+?ZH@_@k\ H@*@qr`H@@X@H@҂d@ H@l@4_H@[@H@_@aH@C@_H@ןH @wH@ I @7H@@5H@wؿ@ `H@`)ß~@H@82n@,H@nAL@H@F+S@lH@h͟@@?H@D@!H@1O@o ?H@&@:vH@l@H@~ @vH@ @H@qߗ@@H@2.ɿ@OH@@_H@H@Y߿H@2G@2_H@3>@@MEH@dl@H@>@SW H@e;@@(H@ `@_H@W@~H@ ğ@_XH@@z 7H@`@>EH@:g@zH@_@J`H@J?@ОH@|߱@WJ H@A ]@H@=/ @2~H@@ZfH@3N)@ueUH@O% @x1 9H@ BP@% #H@p ?@Ju H@-VK@rZ @H@g;_@ZU@H@״ @ H@П @`^H@u @KH@ S @ _!H@_$ @@@H@/ @tH@v @ H@E `@?H@LB@H@H @_H@Kŭ@<H@ @\H@@3H@_@@@`H@H?@ =H@>$@M@)H@q?@v H@eߋ@UH@#ٟ@VH@E#@ QH@@d)H@ @WH@%@. H@-1v@H@t@H@b@b}H@by>@iH@)k@h@WH@?_@7G6H@(?@ H@ކ @N=_H@>@ H@@4H@?+@H@3@@H@I@$t`]H@@j5HH@S@&@H@:?x@L`H@@ H@, @rrH@SI@ =H@@lH@(O@,H@+@"kH@꿵@KH@C@P?)H@P&O@RH@/d;^@|ߥH@/y$@:H@/J F@FH@˙_@Y H@@#@H@s+@58_H@S q@H@dB@ JH@bw@''H@i_@H@H`9@Ê H@B v@YH@g_@H@@Tj@Y $H@'+Lz@d)H@%@f@C4*H@_d@oc?'H@3u@&@H@@}_H@~@2H@@ H@_@pKH@ٗ* @ZH@*\@Q@H@\@[H@E"@?H@@OdH@5_#@fB_H@|@/ H@ @9+lH@* Q@GH@aC`z@l?H@%?z@H@ g@W`H@Oر@_H@@d)H@by@5uH@P-@j H@g?@4 -H@"_}@)@H@8ߡ@@H@Ia @/H@?<@b@H@oU@S߮H@@҂H@_χ@_H@ѿ@zoH@y@H@?_q@/H@ٮT@oh@{H@ц `d@@H@ S@9H@׿S@tH@m?S@-@7H@8E4O@cH@!Q N@;߀H@0aQ-@'_H@K+@IN`,H@+r!@VH@EH@R`@v"@@H@ٟ@H@. @_mH@uv@ ;H@@]H@vu;@11 @H@3@nH@Y@ 8H@ҫ-@*hH@8Z @(H@v @H@)NAR@-@H@"d(@w@H@ߣ@#H@9@͡@H@:~@6 @H@'j@bH@@`, H@ @_)H@g*@Ü@lKH@T;`@.:?H@7T @?_H@&4e@{<H@p?ܗ@~ H@3@H@ ` @S@H@_ @5H@"@6_H@쟆@ @H@u@4<0H@$@Y H@I@І@BH@%@H@OM΃@N| H@ ۪k@K'H@;@?AH@A@?UH@I }@baH@;`Gy@tH@w@H@DHv@lH@u@H@! zt@;_H@4 r@OH@<_q@@H@ @'q@u H@5p@`H@p@y*H@n&p@G:H@2){q@sH@q@7H@Dr*cq@;H@?p@߱H@+ Vo@va_H@8l@>EH@+ j@_H@<%R`"j@wI? H@h@]`'H@߽g@ @HH@4_c@$H@0I`~c@͓(H@ub@E|H@E Eb@v@H@ka@k?H@Od7_@ H@O_@?oH@`@?H@;`@bH@P@b@1 H@z)Lc@sOH@rc@6_H@>Ad@fB_H@`d@LA ^H@gߞe@bH@Z}g@H@p֟Hh@v %H@mh@tH@&_h@H@Oi@)2H@?h@o H@%@l@H@?n@Ym_H@ o@->H@ r@ H@֡t@_H@u@H@ߪv@ H@nRM Wx@UzH@(y@;?H@q.{@_H@Bc|@k?IH@g~@_H@xĶD@H@I"g@GH@@H@b:B@@+rH@1_|@9nH@Ku@=}H@ x@bH@;@@I@l| f@ TI@?@2I@vI N@0I@҂d@*hI@(@&`AI@U@ I@{&@;?I@@I@з?@KqI@@@AxI@@JI@п@;R <I@GR@cv3I@ؿ @6"I@K @5I@o$߄ @PI@?@$ I@?@]I@*Ʒ~@?]I@S @9C?I@S @'I@|v@NI@YNj@# I@Y@I@&H*@I@3#@F II@܋&@ @iI@&@u)@I@f.@|ߥI@0#@v0@ I@3@@I@J 5@ޚ I@wP`l7@?I@w?8@ ~I@;`&;@\I@#;@b`H@;@H@J;@$H@ 2;@~ UH@,?:@&@@H@_D?^:@7,H@g_*9@_H@-7@H@G,6@H@3@H@|`1@,H@,@_H@= *@x}H@5)@/`jH@7`O'@PH@k-#@KqH@A7 @&`H@r@H@;}@tH@#@fqH@a@z`EH@J@eZH@ @X@H@>C@S?H@@3H@vs@qhH@j@HH@/ן!@M#H@M $@_H@_%@H@<:'@_H@\*s(@?H@O_(@U `H@ 2)@=jH@?)@H@5=*@H@˲P+@@H@FW_*@2H@դ%)@V `H@WJ )@H@mo)@H@N@)@> @LH@+@v H@R,@H@M,@YH@<>\,@_WH@?+@.H@jx+@iMH@+/)@H@T'@Ju {H@b/$@c7H@Z'#@߱H@3@#@Z_H@2"@S vH@aP!@cUH@N-!@~@GH@1@@S.H@RŸ#@!H@69@_H@O@> @LH@r/@r?H@>@2-4H@G?@?,H@G@_H@@>@%`H@b@ H@cv@~H@z @?H@?@qH@` @PH@K$@n@._H@Kڿx@!H@&@cH@G' @s@H@C@lXH@xE@/ H@:P@WH@]a@_BH@}@.H@4@cH@  @Ǒ?H@#;@-VH@aR:`p@H@$@ueUH@L@?9H@,@@bH@N@LH@O@ZU@H@w @v@%H@J @G~RH@ԟ@_mH@@l =@@H@PS{@H@=@+rH@'@6H@ "@]@H@t@H@"P?@ H@B1@HH@!c@"kH@U @[H@VN@?H@ʋL@JH@>&@jH@fB_@/"H@q$@@UH@X?@% H@K @ `H@_P@ oH@}@ PH@n@ H@Y7ƹ@H@xH@ @_H@ @\#H@0r@+7H@ÿ@0 \H@ o@H@i@ H`H@R0@Ro?=H@G?Ҙ@J'H@;B@:@s@H@9Qח@&@@H@V@;H@Ӂ0@ H@@H@)^@4 H@! @H@/ @q@b`nH@PvL@@2TH@  @>]AH@@;H@)!@6H@ËՆ@7H@;@ԑ aH@& @H@5?R@H@ܟ@Ym_H@*ǿ*@CH@`@vH@ş}@H@'|@DH@%, 8{@NH@z@@XH@# y@^{H@8TJw@߭H@ t@_H@?*m@@H@_li@7H@b@ԑ aH@E `\@SH@5W@H@/7U@ޚ H@8Z S@2~H@RN@LA ^H@EX_@@x1 9H@kT=@)@H@!S ;@@XH@?_W9@O_|H@)8@g_H@)6@|@ H@o`4@2H@3џ2@ MH@@0@?YH@/@*@GH@72@&@j5HH@&@8XH@I"$$@)H@;#j@GH@J@YH@oL>@cwH@+@H@ r@F IH@tz@@AxH@@[H@`&9@H@d@iH@D @H?H@@ H@R@ؘH@aF@OYH@{ݿ@?VH@@7H@9n@hH@i 1@MߩH@k @VbH@yK @5H@*@ H@ٕc.@kH@Q1@_H@'T?4@QH@E4@N PH@;Q3 R>@|`H@WI;2C@~H@e;@C@b?H@ X?FD@_}H@cN@7H@X7 :O@UH@{gY@pH@| _@nH@l_@G' H@@}_@`YH@/[@H@MT%Q\@H@7@^@pH@Yh@lH@]?)k@$t`H@C@Sm@H@>\0Wo@+H@IQ`Ct@x1 9H@&4eu@wPH@:]w@tH@Ax@ngH@k[9 y@dH@9Wޟz@oc?H@{@B?H@~f|@3 H@@ŭCH@MK݃@V4H@x1 @%0H@1@cv3H@@&@@H@a_@H{H@}@v@H@Ia @FH@G@H@Y߿@H@@W`H@W@o$I@)@S.I@J@^I@ `@2pI@K@fB_I@jqި@.I@"4@q@`4I@ߩ@= ZI@M:4@9+lI@٬@ ~I@g'ſ@,nI@ Ү@I@yo5@tI@_i@I@%@0 9I@@ZI@@^_kI@! z@|cI@A͟@/"I@R@pI@)֪@,)I@ٟ8@bLI@O`@mI@|X@ I@؟@nI@dޫ@J`I@_@WI@@@I@F*ԯ@KI@?a@ I@1@WI@:Q@I@Ű?`@?bI@Z@O۹@oKI@+3@@BI@0@0 9I@@8I@_@k_;I@0@/e HI@ V@@?jI@җ+@7I@l@I@z ,@k_I@CH@2I@__@G' ]I@M@ɠ`vI@ɿ@@I@쿭?@I@?M@.nI@M0@1eI@ì@V `NI@:@o 1I@@@mI@@4_I@?@I@| f@ TI@W=@qH@Kŭ@PH@LBȊ@#H@@&H@YK`@x}H@EL`@לH@U)@kH@B!@H@ӕW@H@,@YH@;}@_XH@?@D_PH@忴@;H@Ƭ0@H@y(f@h?UH@ `@ _!H@?k@B8H@F?@-VH@8`@U;H@ٟ@G~RH@@&@1H@@H@6@PH@?X@xH@6@@)@6"H@s@P?H@H @Ǒ?H@.%` @zH@ASD@"H@*\@dH@EX_@m?H@ @H@Kŭ@l?H@c2@״H@_9@<6H@'_n @wH@3@!H@s @H@:2(@0I`~H@/:@H@ @>EH@ _.@Ê kH@!Q @YH@}6`F@J`H@ 7 |@]`'H@޿ @^ H@I@L@H@`@?H@]@4TH@z@\H@ @ @7 H@R0@f_ H@3@f_ H@@f_ H@ ?@xH@P߶o@;_H@[@6@͓H@) @/"H@(_0@H@o Ͽ@ W@\H@+@jH@D@@?fH@8~@XH@?@DH@N@;H@@X@, H@@WH@`&@@d`H@;Q3 R@`?H@s. @*H@e<@X@H@v@sVYH@`P@Y:H@9:@y@H@Ls@_H@t( @<H@_@`kH@1ܱ@(gH@-#`׿@ H@UR@=@ nH@IxJ @_dH@6ź@baH@A=@ eH@L`!@_hH@a?m@5uH@Ꟗ@$H@δ@bH@3\@iH@T@H@״@!@H@RS@@|H@%ϛ@H@" @H@7_@'_H@{@.:?H@(@@->H@m@΋@ _H@;?<@N H@n&ˈ@&H@~@LH@ -c@tyH@@gH@"@`UH@9@Q@?,H@W]$@@@H@1_@TH@i_@@AxH@KI o@`OH@@@?>H@OO@,@8H@ @(@H@ ?}@H@" z@H@$wv@) H@FCOr@_H@ _Co@H@wRm@4H@}!`k@H@$ÿBi@\9H@B_g@HH@V'@f@H@=_f@H@t7@zd@H@@_@H@/]@`zH@$\@>EnH@aW@=ZH@z_U@"JH@mR@y'H@wFJ@qH@!@bF@.:?H@C_5B@ _gH@ 7?@H@Aߓ=@Ro?H@21<@vH@JN`:@OH@bM 7@H@ 25@:H@zߐ3@xH@`j0@r?1H@;,@(TH@ (@PH@kT /'@fB_H@k:$@% H@zT@H@~r @H@b@sH@\@L`H@ :f@-`VH@ۦ6@@zH@hQ @H@%[@ H@[@ 1H@@qEH@G0@ ZH@̀?@Y H@t_K@g*@H@?@_H@̮A@''H@]: @$H@i9`?@H@@WH@ @ـH@@$1DH@5< }@ XH@r@2H@/@ H@@&6H@ 7@S@hH@߅R X@H@m w @@H@8̟ @H@l-@ @H@Q@XH@.K{@њH@DE @rH@&Aџ@2pH@?"@PLH@9@P H@6g@$H@C@ 8H@W=@ tH@@BH@K @ H@ZT8@8@@H@@V `NH@& @ɠ`vH@Lv@:H@K H@$t`H@X?{@H@k@T~`9H@^9 @`YH@aN@hH@ٮT@o@H@ @/"/H@. @AQH@ ` @P H@=@_H@RGr@0H@5`@CH@EDֿ@_lH@ O@_H@?@H@-$`t @OH@@ @Ym_H@ @(H@ @k\ H@  @(H@Զ @FH@i@NH@84`@Ǽ H@B@'H@<@>H@~@ bH@&S`\@\!H@8E4@F H@P@?H@C@u& 3H@!@QH@^ɟ @Y $H@pI "@# H@/"/%@H@=)@Z_ H@(6@AH@K:@@H@vu;<@_H@HF=@wI? H@I>@ H@U@-@@ ;H@״@@@KH@I A@nH@}C@,H@1 ZC@L`H@>TD@H@V{D@BH@D@gH@/ >@1H@?@fH@R@3H@?Q@ H@'S@;R H@U@?H@.ϿvW@?H@M@%b[@H@#@^@IH@_g@#H@2s@PH@{@@)$H@ǿK̀@u& H@@H@LBȊ@#H@8ٟ@H@qӟ܆@5H@0ICD@9H@E@`H@0G@ŭH@RH@1H@:OK@H@ ^L@H@'M@H@N8`M@H@7O@H@P@H@ )S@ H@)#.V@3H@=Y@?H@[@H@C\@xH@]@y MH@9[^@+H@w_@mH@9,`@H@t8a@Ǒ?H@}֟ib@DH@D=(c@=H@cf@>H@QEh@kH@k@;?#H@R q@v@%H@12?t@@*H@L;@w@ H@e,`#y@H@ޝJ@+|@# H@wF~@5VH@jG@ө 4H@_@^H@1@CH@|@#5H@@+zH@N_a@0aQH@@ *H@o$߄@y@H@^@Z_ H@. Q@+/H@I@~@=H@#Q`z@~H@'Qw@,ߦH@_5{@?oH@] ~@~ UH@2@EH@ @%,H@'@?_"H@qӟ܆@ОH@9@ͅ@RIH@u@ H@>p@wH@t_z@>EnH@W33z@ H@h:_w@ H@(;& `t@`zH@>@{w@H@wP`l{@`YH@f4|@o ?H@.@H@@жH@@ H@A@3 H@A <@? $H@Ag-`]@@)$H@":U|@v@%H@tQj|@GH@uSl|@߭H@׮z@2_H@2D%u@ ` H@Fq@~H@l,qp@=uH@nT`p@?H@q@FH@aA+x@ĆtH@ "z}@-H@ u@3H@0ICx@ _H@_ `Fx@ H@dH`w@H@ִu@H@0?u@G`H@Iw@ H@~Q@p@H@ Xp@r/H@3S@Vk@H@~^+g@ǻH@pc@ECH@j_@0H@M`iV@)K@ƻH@'U@1ûH@>pT@J2H@U@-L@H@L@4_H@w:L@" H@l_K@ H@rERG@H@@ߎ3@H@D=(c@=H@}֟ib@DH@t8a@Ǒ?H@9,`@H@w_@mH@9[^@+H@]@y MH@C\@xH@[@H@=Y@?H@)#.V@3H@ )S@ H@P@H@7O@H@N8`M@H@'M@H@ ^L@H@:OK@H@RH@1H@0G@ŭH@E@`H@0ICD@9H@}K?@5H@D@>@`+H@PLd=@ tH@"@<@z`H@ @@J:@3H@&?6@.H@`L3@0H@1@:H@24$0@ LH@14K.@gieH@,-@@H@EƟ,@KH@'+@%_H@J(@)K@FH@9 [&@ H@U%@7H@6%@_H@$@tH@$_K$@H@()=$@zH@ #@\!H@E?#@?-H@?d@pߘH@_@H@2@`H@`s@ H@@wH@@ AH@,EU@DyH@(?@ H@Q޿`@Ê H@C`Y@b H@P@''H@q_S @\3H@߰ @GH@^m@ L VH@+@ W@\H@ӬC@6uH@M`|@IqH@ҟ`@*hH@_$@?@H@@@ߙH@G +@}߶H@5)^@m@H@-U`m@5H@:?x@"e?H@v@O`H@ r@VH@N!s@`H@ٿ_@_H@+q@H@1@H@@@)c_H@|@H@t矅@=`H@H@wH@E"@H@wI? @_H@Fַ2@H@7@)H@傯W@* QH@@@qH@e@]`H@-B@|H@D@ H@۟@TH@*@1CH@}_@_lH@c̟g@U H@1*@H@ `@LY2H@@LvH@؄@AH@ZR y@OH@_.@ H@=a @8@H@D@2@@_H@(@@>H@V_@ H@f+?-@;H@*@i_>H@x?@ؘpH@ȿ@X@H@i8@o`H@&(@6"H@%@g*@CH@s @eQH@`$@/`jH@2!@@}H@IN`,@@H@@?H@¿c@H@P@J`H@K@H@1Z@F(H@j " @INH@#ȵ_F@H@L'@E|H@j@mpH@ʳ? @1eH@? @QH@\@L`H@b@sH@~r @H@zT@H@k:$@% H@kT /'@fB_H@ (@PH@;,@(TH@`j0@r?1H@zߐ3@xH@ 25@:H@bM 7@H@JN`:@OH@21<@vH@Aߓ=@Ro?H@ 7?@H@C_5B@ _gH@!@bF@.:?H@wFJ@qH@mR@y'H@z_U@"JH@aW@=ZH@$\@>EnH@/]@`zH@@_@H@t7@zd@H@=_f@H@V'@f@H@B_g@HH@$ÿBi@\9H@}!`k@H@wRm@4H@ _Co@H@FCOr@_H@$wv@) H@" z@H@ ?}@H@ @(@H@OO@,@8H@@@?>H@KI o@`OH@i_@@AxH@1_@TH@W]$@@@H@9@Q@?,H@"@`UH@@gH@ -c@tyH@~@LH@n&ˈ@&H@;?<@N H@m@΋@ _H@(@@->H@{@.:?H@7_@'_H@" @H@%ϛ@H@RS@@|H@״@!@H@T@H@3\@iH@ hIxJ h@^;H@ 8e@C4*H@*BH@@TSH@1@H@O@giH@Y @H@+ @mH@U#`M@xH@_@3 H@IQ`C@XF&H@V 5@`'H@;@(@i&H@v @,nH@EM@ H@0-@WH@f_@tH@|ο< @WH@0 @,@H@T"@H@cQ%@P?H@sj_6'@?H@ ? (@PH@r)@xH@t'+@ؘpH@nxm.@ՍjH@_O0@ՍjH@%+2@>EnH@_3@ yH@9,4@i_H@a?m6@xH@a淿7@U H@uv:@*H@ϣ<@H@O=@v 5H@G@>@]H@@kE@a H@R_H@PH@jK@H H@|?rN@b H@`?hP@jH@{T`3R@QH@; #V@DH@:W@MH@[ Z@/ @H@/N^]@?H@@&`@ yH@Qc@Ro?=H@$a@?_"H@`@H@o]@H@o\@vH@?b[@?H@i_X@SW jH@_ Y@48H@IY@_H@_Y@}H@9_tZ@AzH@"@\@x? H@>\@ H@(k]@dH@i_^@̫|H@wO_@ TH@kLH`@#0H@o:Ub@HfH@.d@_H@ 8e@ ZH@Hd@mH@<`d@#RH@(`}d@H@N`@\xH@Y_@=H@ s%_@HfH@B4^@d`H@3m^@(@ H@,H^@ H@Hc]@ H@g`]@H@(\@-H@~X@H@:W@k\ H@9WޟV@IH@g9V@E?H@_U@a H@TU@%H@F_U@''H@9T@9 (H@ExT@'H@U@-T@v %H@MCT@6DH@ֿ-T@@pH@oH@S@uH@34S@e @H@kR@#H@_LRQ@mH@KP@xH@#N@H@ݿL@WJ H@vJ?vJ@f H@&)G@7H@O`D@H@_C@~ H@,H>@0aH@ # <@1H@@%0:@aTH@9@+H@^?I6@H@އ,3@PLdH@fN1@H@Ǽ /@Q H@.@BH@ff.@+H@U `.@\H@C`8-@tmH@*@5{@SH@ڪE(@>H@\F&@y@H@L $@H@|S#@H@c5"@|`H@?L!@ߌH@=@ @(TH@@Li@ H@S`@zH@;7/@H@H@>H@o$߄@lH@0@WH@N>@8H@{g @ H@ T @(H@l @H@2߉@_H@wܮ@va_H@M:4@2H@4@}6H@p@wI? H@ĴN@! H@@S?H@@@H@(@`=H@} @@\_H@ _%@@Ju H@ڿ @v H@r?9 @h@H@,@?H@}!`@ bH@u@H@?@aTH@(@tH@9K@ H@j@H@;@?H@4@H@O@1H@0LC@H@L@RH@&@H@2L@{{ H@R@q H@R?@*NH@v>@6 @gH@S)ߗ@QxH@F6 @)H@e:@WH@}@b}H@H@PIW@f_H@i_f@H@St@l?H@-@tyH@@/ @qH@@ \H@@;H@v@̫H@?n@eZH@Ah_Dz@H@^9 @H@ؙڭ@ H@,'@cH@H@ H@?@c7H@ia@H@6-B@ɠ`vH@+ğ@d^`H@7@@?8H@՟@@H@9@->H@@O`H@,Q @ H@g@H?H@>@@yH@E@H@@hH@V߀@SH@E @t_KH@c–@J`@H@??ʔ@^;H@}`ő@ =H@o@AH@He/@*NH@} F.@`H@QH@6"H@;@sOH@_@J2bH@C#TZ@)H@F,ޟ@H@@[H@mJ`@H@λb@yH@[@6}@aH@*.x@3H@EZ2{@ `sH@r՟q@H@W7U@ɠ`vH@ݵ5@''H@0t Dy@* H@cy@H@!S s@ ?MH@IxJ h@H@A`ai@/ H@>zj@||H@*uEr@ H@-.w@dEH@_ |@_H@I8{@H@>\0W{@PH@OB{@ !ߐH@,@HbH@r?φ@o 1H@@ SeH@Ϳ؅@ _H@>]@u@H@w 5@o H@d[Ӗ@H@@Tj@eH@ц `۠@H@?@2pH@@j5H@HM @Z ^H@i_f@ZDH@d@zH@eC_@ H@@B2H@@CwH@1}@}_H@ |@_pH@>7@7H@@0 9H@]Iٿ>@H@oU@S߮H@?<@b@H@Ia @/H@8ߡ@@H@"_}@)@H@g?@4 -H@P-@j H@by@5uH@@d)H@Oر@_H@ g@W`H@%?z@H@aC`z@l?H@* Q@GH@ @9+lH@|@/ H@5_#@fB_H@@OdH@E"@?H@\@[H@*\@Q@H@ٗ* @ZH@_@pKH@@ H@~@2H@@}_H@3u@&@H@_d@oc?'H@%@f@C4*H@'+Lz@d)H@@Tj@Y $H@g_@H@34@} uH@S@cH@/v@*3 H@lSf@MH@@H@7@H@B?@2H@ߖ@_ؿH@;_@5H@ Jڟ@9nH@ٗ* @2pͿH@_ג@H@<t@t}(H@߽k@AH@] _X@|cH@ NW@eH@1]@KH@p`@ H@'`\@~H@ե=X@oXH@NܿO@H@ TƿD@`H@hNB@m?H@aS=@;H@1A@hH@D B@H@٬B@/e H@ƿB@4H@ C@H@N@B?H@+N@H@O@H@(9U@:j?H@X0_@06H@f@H@U@m@hcH@j_kx@`(H@z( x@%0H@*.x@3H@[@6}@aH@λb@yH@mJ`@H@@[H@F,ޟ@H@C#TZ@)H@_@J2bH@;@sOH@QH@6"H@} F.@`H@He/@*NH@o@AH@}`ő@ =H@??ʔ@^;H@c–@J`@H@E @t_KH@V߀@SH@@hH@E@H@>@@yH@g@H?H@,Q @ H@@O`H@9@->H@՟@@H@7@@?8H@+ğ@d^`H@6-B@ɠ`vH@ia@H@?@c7H@H@ H@,'@cH@ؙڭ@ H@^9 @H@Ah_Dz@H@?n@eZH@v@̫H@@;H@@ \H@@/ @qH@-@tyH@St@l?H@i_f@H@PIW@f_H@NH@>H@%, 8@F H@pެ@?H@@fH@*!@LY2H@_@5dH@@6 @gH@R?@*NH@R@q H@2L@{{ H@&@H@L@RH@0LC@H@O@1H@4@H@;@?H@j@H@9K@ H@(@tH@?@aTH@ @s@dH@_5@+ `oH@@2~H@^?.@H@_ @H@O @2H@:>@r/ H@,!@H@wؿ$@:j?H@X(@tH@~ڰO-@ H@pH.@<-H@40@baH@1+3@ߌH@s5@nH@H6@l H@n;#8@H@_ @@UH@C@|`H@S E@s_H@m&ZF@H@6F@o H@DF@Ǽ H@5F@H@բ1G@ H@R`}G@XH@PG@_H@䶿H@H@iI@KH@J@nH@3N)J@`H@EJ@?H@K@3H@cxK@@@H@M`K@*H@%K@?H@ `K@H@RC L@RH@Z/L@(H@ ~ +L@H@7*L@H@pL@H@º_L@U H@lo" L@H@iL@3 H@ `&L@_H@Y.SL@X @H@{_L@H@N@9fH@6~N@G' ]H@t$N@-`VH@P = N@%OH@0`,N@Ah_GH@RN@ ?H@DN@\3H@N@?(H@B{N@ H@66N@^H@N@BH@aSM@xH@M@v H@< 翬M@c H@f~?M@:H@(߿M@XFH@48@M@?H@RŸ#N@(gH@2-4N@_H@_9N@H@ S1N@@?jH@8N@@cH@HRN@ \H@*`mN@YH@EDֿN@DWH@0N@ueUH@bO@SH@XP@PH@x? Q@vNH@#5;Q@2pMH@Q@9JH@; #R@ _CH@QCR@j@G?RH@t֟j@t_KH@I;j@v@H@" j@58_:H@ jӿj@z?4H@ ?j@1H@?j@e @/H@-k@`k-H@'l@y'H@u_l@H@Xm@cH@*yn@H@ @o@N%@H@_Zo@2_H@"P?p@ H@6up@qH@'p@H@)^q@KqH@yH@q@ H@ r@H@65-r@(@ H@y.Kr@ H@=``r@X @H@:r@x? H@1_s@`=H@<ןs@ _CH@# t@HH@u@[H@_bu@@@`H@-6 u@?fH@au@N=_hH@>w@lYH@<_y@w`QH@@@H@ƕp@}6H@ `>@'H@=@H@ O@H@ƘG@}@ـH@ n@ܣuH@*@'jH@b0@״9H@3֔@/"/H@U `@H@$_K@rZ @H@@UH@9_٢@H@@ H@3D n@{nH@&l_p@\H@N@lYH@v@HfH@o@hH@ !@ @H@+@8?H@?'@H@*@͓H@G ^@xH@i@}_H@\L@K@_H@C_5@~@GH@,B@@va_H@/@ _H@?b@H@(@\H@;,@?YH@9@Q@TH@ `?3@`H@W?x@ŭþH@TM @ nH@:@j@?H@F@ݾH@R@sH@- }@H@"n@T[H@G}'hf@ڿ_H@"g@О.H@9@0g@c7H@2;g@u@H@_e@q3H@ ,d@_ H@F^@0H@ğUX@?VH@1?J@"kH@_I@H@.)N 9@2_H@S5@NH@@,@wH@OY+@?YH@z)+@ QH@N.l(@`H@ M:4@$t`]H@}K?@ @H@ߴ@H@Y"@@e @H@KT@(@H@8~@kH@R4 @P H@l@,H@Fַ2@H@wI? @_H@E"@H@H@wH@t矅@=`H@|@H@@@)c_H@1@H@+q@H@ٿ_@_H@N!s@`H@ r@VH@v@O`H@:?x@"e?H@-U`m@5H@5)^@m@H@G +@}߶H@@@ߙH@_$@?@H@ҟ`@*hH@M`|@IqH@ӬC@6uH@+@ W@\H@^m@ L VH@߰ @GH@q_S @\3H@P@''H@C`Y@b H@Q޿`@Ê H@(?@ H@,EU@DyH@@ AH@@wH@`s@ H@2@`H@_@H@?d@pߘH@E?#@?-H@ #@\!H@()=$@zH@$_K$@H@$@tH@6%@_H@U%@7H@9 [&@ H@J(@)K@FH@'+@%_H@EƟ,@KH@,-@@H@14K.@gieH@24$0@ LH@1@:H@`L3@0H@&?6@.H@ @@J:@3H@"@<@z`H@PLd=@ tH@D@>@`+H@}K?@5H@& =@H@ÍJw9@$\ @H@&6@7@! wH@sZ4@@XH@IM7`2@ DH@A1@g+H@J ,)/@P H@@RM-@L_H@eG,@H@l*@kH@ G*@ W@\H@C(@9C?H@ g'@(H@uv&@H@E $$@ H@$F"@S H@e,`#!@Z H@ @ H@y@/"H@_l@ `H@Y@(H@J)@\H@3u@G??0H@뿔@4TH@M@sH@# ?u@H@n+ a"@H@fm \$@@H@F&@^H@)?'@}H@5+@ L VH@ -@G:H@L_=/@`$H@(E1@ H@.3@&H@yA?1@ZlH@'.@.H@u)d,@H@u*@S H@P5_)@KH@y1(@"H@;&@ `H@ǀO $@m?H@n"@kH@@߼ @/"/H@)@?8H@jq@;H@%O@?8H@:?@4 -H@A@@@H@!;@HH@ow@DsH@d@cvH@0? @fB_H@( @f[H@" @}9H@K_" @H@z @H@I7?@^_kH@pM@RIH@LB@r?H@X@8H@ @?-H@M@tH@@ H@Iy @C4H@d@QHH@#ȵ_F@J`H@6L@_H@ng@d`H@ @ `H@;'G@ H@ٟ@H@4!1@58_H@ M@wH@ҟ@LH@l.@@H@2`^@;^H@?'@H@+@8?H@ !@ @H@o@hH@v@HfH@a>N@lYH@ӿN@+H@ @j H@i @'H@_2@ W@H@E@H@ޯ_@N H@ɼ@H@ÞǺ@0aH@`ϸ@H@*" @H@^G@ECH@d R@2~H@W@VH@)_@H@8@_H@Jq@$t`]H@/?`@4_H@w@/ H@`@b`nH@ȧS`@H@<@_H@Ŀ@ĆH@C@j5HH@+@H@j5ȩ@H@`@_H@o#+@ _!H@:M@-VKH@@'H@ƕp@}6H@@@H@<_y@w`QH@>w@lYH@au@N=_hH@-6 u@?fH@_bu@@@`H@u@[H@# t@HH@<ןs@ _CH@1_s@`=H@:r@x? H@=``r@X @H@y.Kr@ H@65-r@(@ H@ r@H@yH@q@ H@)^q@KqH@'p@H@6up@qH@"P?p@ H@_Zo@2_H@ @o@N%@H@*yn@H@Xm@cH@u_l@H@'l@y'H@-k@`k-H@?j@e @/H@ ?j@1H@ jӿj@z?4H@" j@58_:H@I;j@v@H@t֟j@t_KH@by>j@G?RH@9j@8XH@T"k@aH@Uݟbk@AiH@ k@etH@(Tk@~H@ k@7_H@k@.} H@#u_k@v@H@I8k@H@'4 k@Ώ_H@1 k@v H@&@ok@ H@0 9k@&`H@߳j@H@kj@@H@_rj@H@ۻHj@H@޿i@H@Fi@AH@ixai@rZ @H@~+i@y H@=h@ H@0g@.H@o.f@D H@(f@H@g_e@`H@7e@MH@Ye@1H@5/e@H@%m_d@,nH@c4?d@a H@)?/d@x?H@d@!@H@jc@6H@@,@c@? H@&@r/ H@O @2H@_ @H@^?.@H@@2~H@_5@+ `oH@ @s@dH@?@aTH@u@H@}!`@ bH@,@?H@r?9 @h@H@ڿ @v H@ _%@@Ju H@} @@\_H@(@`=H@@@H@@S?H@ĴN@! H@p@wI? H@4@}6H@M:4@2H@wܮ@va_H@2߉@_H@l @H@ T @(H@{g @ H@N>@8H@0@WH@o$߄@lH@H@>H@;7/@H@S`@zH@@Li@ H@=@ @(TH@?L!@ߌH@c5"@|`H@|S#@H@L $@H@\F&@y@H@ڪE(@>H@*@5{@SH@C`8-@tmH@U `.@\H@ff.@+H@.@BH@Ǽ /@Q H@fN1@H@އ,3@PLdH@^?I6@H@9@+H@@%0:@aTH@ # <@1H@,H>@0aH@_C@~ H@O`D@H@&)G@7H@vJ?vJ@f H@ݿL@WJ H@#N@H@KP@xH@_LRQ@mH@kR@#H@34S@e @H@oH@S@uH@ֿ-T@@pH@MCT@6DH@U@-T@v %H@ExT@'H@9T@9 (H@F_U@''H@TU@%H@_U@a H@g9V@E?H@9WޟV@IH@:W@k\ H@~X@H@(\@-H@g`]@H@Hc]@ H@,H^@ H@3m^@(@ H@B4^@d`H@ s%_@HfH@Y_@=H@N`@\xH@(`}d@H@<`d@#RH@Hd@mH@ 8e@ ZH@.d@_H@o:Ub@HfH@kLH`@#0H@wO_@ TH@i_^@̫|H@(k]@dH@>\@ H@"@\@x? H@9_tZ@AzH@_Y@}H@IY@_H@_ Y@48H@i_X@SW jH@?b[@?H@o\@vH@o]@H@`@H@$a@?_"H@Qc@Ro?=H@x e@`OH@9nj@Ju {H@k@H@bM o@jH@ ut@ @H@$@y@r/H@,@{@`H@I~@wH@)@.nH@ҙ(΀@WVH@ 6`@H@1$@,@ _H@T@H@:E`@?H@Y@@H@e@H@ߴ@H@ X:?x@e @H@]: @?bH@h-6 E@`, H@NI@P?H@NJ@SH@\*sL@ uH@EM@^mH@/N@@?jH@A O@kH@O@%_qH@忓P@q yH@?Q@?H@a_S@?H@?T@<H@[U@BH@2X@`H@+:Z@;?H@º_\@etH@ ~_]@G~RH@!h7]@8/H@N49^@F H@"? _@`H@?_@SH@~`@AiH@3EH@ s@H@a u@`, H@?z@WJ H@1Y|@11 @+H@}@J`@H@O @mgH@@@) @7 H@1 @. H@˄@^H@ @H@V'@@:H@ZR y@* QH@ם՟P@YH@(?@҂dH@? @b`nH@! @Ym_uH@,@n(`{H@@@ `H@ +&@0 H@I7?Ý@(@H@˷_@H@@ H@+෥@ oH@#N@v@w@_H@XC@>H@>;@6"H@'D@G`H@۟@?H@ɿ@kH@ޛ׿@ 1H@ O@0sH@`@j H@C N@+H@$ÿB@r/H@_)@(H@mJ`@ eH@K@e@=?H@U@=uߔH@ @V4H@n{_z@ H@ս_@ZH@z?@kH@ܟ@7H@% @tH@_v@_H@>;@7H@@H@D1@H@߃@:H@mo@\H@'_n@ H@-$`t@)c_H@n{_z@_H@m w@H@j,@_@H@#%6@:H@y_@@ZH@do0@H@% @VH@5@6 @H@*@_H@M`@h@H@@DsH@k=@&@H@*&@ߢH@zŸ@l?H@º_@ jH@hbb@n @H@t@ H@9@@cwH@W=@ tH@C@ 8H@6g@$H@9@P H@?"@PLH@&Aџ@2pH@DE @rH@.K{@њH@Q@XH@l-@ @H@8̟ @H@m w @@H@߅R X@H@ 7@S@hH@@&6H@/@ H@r@2H@5< }@ XH@@$1DH@ @ـH@@WH@i9`?@H@]: @$H@̮A@''H@?@_H@t_K@g*@H@̀?@Y H@G0@ ZH@@qEH@[@ 1H@%[@ H@hQ @H@ۦ6@@zH@ :f@-`VH@\@L`H@? @QH@ʳ? @1eH@j@mpH@L'@E|H@#ȵ_F@H@j " @INH@1Z@F(H@K@H@P@J`H@¿c@H@@?H@IN`,@@H@2!@@}H@`$@/`jH@s @eQH@%@g*@CH@&(@6"H@i8@o`H@ȿ@X@H@x?@ؘpH@*@i_>H@f+?-@;H@V_@ H@(@@>H@D@2@@_H@=a @8@H@_.@ H@ZR y@OH@؄@AH@@LvH@ `@LY2H@1*@H@c̟g@U H@}_@_lH@*@1CH@۟@TH@D@ H@-B@|H@e@]`H@@@qH@傯W@* QH@7@)H@Fַ2@H@l@,H@R4 @P H@8~@kH@KT@(@H@Y"@@e @H@ߴ@H@e@H@Y@@H@:E`@?H@T@H@1$@,@ _H@ 6`@H@ҙ(΀@WVH@)@.nH@I~@wH@,@{@`H@$@y@r/H@ ut@ @H@bM o@jH@k@H@9nj@Ju {H@x e@`OH@Qc@Ro?=H@@&`@ yH@/N^]@?H@[ Z@/ @H@:W@MH@; #V@DH@{T`3R@QH@`?hP@jH@|?rN@b H@jK@H H@R_H@PH@@kE@a H@G@>@]H@O=@v 5H@ϣ<@H@uv:@*H@a淿7@U H@a?m6@xH@9,4@i_H@_3@ yH@%+2@>EnH@_O0@ՍjH@nxm.@ՍjH@t'+@ؘpH@r)@xH@ ? (@PH@sj_6'@?H@cQ%@P?H@T"@H@0 @,@H@|ο< @WH@f_@tH@0-@WH@EM@ H@v @,nH@;@(@i&H@V 5@`'H@IQ`C@XF&H@_@3 H@U#`M@xH@+ @mH@Y @H@O@giH@1@H@@TSH@h͟@t>H@ G w@ _!H@:Y@BH@_@(TH@L@/`jH@B@ H@ކ @N=_H@(?@ H@?_@7G6H@)k@h@WH@by>@iH@b@b}H@t@H@-1v@H@%@. H@ @WH@@d)H@E#@ QH@#ٟ@VH@eߋ@UH@q?@v H@>$@M@)H@H?@ =H@_@@@`H@@3H@ @\H@Kŭ@<H@H @_H@LB@H@E `@?H@v @ H@/ @tH@_$ @@@H@ S @ _!H@u @KH@П @`^H@״ @ H@g;_@ZU@H@-VK@rZ @H@p ?@Ju H@ BP@% #H@O% @x1 9H@3N)@ueUH@@ZfH@=/ @2~H@A ]@H@|߱@WJ H@J?@ОH@_@J`H@:g@zH@`@>EH@@z 7H@ ğ@_XH@W@~H@ `@_H@e;@@(H@>@SW H@dl@H@3>@@MEH@2G@2_H@_."@2H@PK9&@. H@ )@WH@G@,@¢@H@S?.@y-H@/@eH@R0@2pH@(U2@@@H@'?53@ H@;n7@s_7H@X8@DsLH@Xߟ9@UH@ ;@@@`H@ؿ<@?bH@IM7`>@.`H@A-@@@ iWH@aA@]OH@8A@cC@ 8H@-6 E@`, H@terra/inst/ex/logo.tif0000644000175000017500000005123614201035747014570 0ustar nileshnileshII*eM=S  H x-1> 255 -9999 0 -9999 red 255 -9999 0 -9999 green 255 -9999 0 -9999 blue ??@S@#      )#     ?mtr@@TXAunnamed|WGS 84|?P8$ ?Pc?"P F_w(~n4>1 ,K"3?fw}O_oN|t,MW?mvV׬V;%g%1zc!ŢԪvwjrl\T̓UlmCL|z;+n5f%eXLR^j]t^%lUIfZYTYL! B%dU%QI QVR1\WE\ZŁn\f)`ftnz*zNJ4 !N@IS9JҵH)J6{/tG#lg>I^n`e;eZ^u@EmVYDpVUHe\A] RV=@SqQRnXiPRdBQbUfa؜˙z R;eb[?x_%vWe8Ax^^\eu\%ifY0UPIRP1Yurܦ9_n[x9~d& e&qbm&1h9™ye~c\/1yΗ]ॶ(XŴNZgSV>QDXJD%ۓ2QD>Pd4J([JJkJ{@i":"| Gtfj쉒˘zۍc0f 2@pe5p5#plH(5c\j 3H c 1|1"\1. " 1! a a!a \.%8c)%GZZeH#j$bMi|~"&zQ9G,Xi dΌ4 :1\-3c z'E2#Ȑbn 'Dy"@O&ĠbVW'\}bLIq $0 F"PEeDTC Q*"DV P*DŽXOmE(2!=CcHI!EDP2#D89 Az/¿T_,l4L%8iHNq-$eH`l F cƌ1߸~sQ18xIXkd!$-ldG T'X؞bO `(f, M+(& E!xa70CX] -@Cd 1`^ L-BR )fC8Z A/|"B $(O <(EdSQ>&yA!0?q pgb\aBa<c&jZm#u xöG 1F&퐧@­Hi1qxZ PQ,!!<X <+C$ <`hP/PX ,㠸`^ .pu6BF%@pc t7v0D 6&-U\RP5DX\D w@*f\$>1* MIu4d8蒱mCn *O#dhA6Pðv#h:£GnCHzA? v! &R(`BҺv4&DF @ p ,l `D & T /@`\ 0FFD`NL`N V flxp !a.LA>ALa.l@ (` tjG|J`$Y!OZcԃ 6GV! ` @dB~nvR@ Z``H`:*"@(""`.@.2`,756@5(`F`8 8o@F$1$E hdfp` 2 (! 06!.lMnzYBX*Fi:a:=A!0!-Jm` @عAd!<!!1!pd%@ z`K) ;$ ,     BQB1:`# +,7-rF@NM-@THLVNR`@R2D2.HR./P`B 2Xnbv '"!8,!@ @ J>aǨ;#*ȽB!L5(sO(!B ๡VaF$!L!:@` ` @}/F+, `@@ B `&.4 $, (``f Pd|vra|~|ԋHHԒejA4: ` prV\YL LZb@ULR ^Nxx $ *A 7 @`P(+mb9B:G;>s#B$~Dm LɲO<@al&DhU!J `pb  C  h3@zaa NDkFզ%z#b*|v `a[/ ]jrU@XL`L`p @  6"$ ` a^#"BR/k,"{{N% "|~&4/f l ` `p!gU! G:xa @ ~F2\ q   b@G!sjct"i#Bn/IԆ#avZ|f-[aa}jZ7bÅv'#a. @@ p h5`v/ ` @u  ut @ !At<%6$pT":Ś#"k&aC ^f5=`l` 6 GnEL'wA!4 /DR\ B@8xV a"F&t"<@|Z+"8;عBj"|*!a*c|C ~syt @ @زM@9<zf @ vЫ&a * @ ` a 2/Ӡ-a `f@a(  rP$A.%B;ZQ"ӝ"|- /bkR c|*A*B'%'B.+BP|/ၢ` @`tך砬 `$`ugy @ 5a b)m>' 1! Kt^*|Y|@`/`C2qW|jamiN7bpT}AaaG 7c"nJP* *q[9:}v!.;N%B~AL&B.4$M\~ ` t !DǨxD#$R46a0 yi% @=Fʄdhs>Y[ r!A .h!Dp"RjbG"~ahƅAƁr|ha@At`AEɼ|A~d!P!!rfaO\Talta!"*$Wi;&_A| [O<g dB#xHSYF-01&&F xYb bS"@c$X @zqr@t#qx=Ѡdv"½F.%FrAѢARa~XtE_hrr^#e Raf&Fyx<$$$f$P!La<ᐛI&!z8%:cVF~ڤ :^ VP` ೺ ` SS3-\aͨfF`4  ڶAGk7JAcn\%q *O#"J!2!apvAA|aɁtΆaarAAaramA_Aߛ†aДDj`!v AL !" 1([/Zo7MQ_1˨ |:N9`0e~"7g ϗh,FEn4+%Ab(J˄̜N?wbO!  _2Sc(K4m|T3 k97}[t]{Wtۮv=ïoV9^~K\빼h>ByXJH1d,d5aX먇z9C3 x5 hDD=KEnX}@pGl{Ihf1fdgYp H)8v#=qA)rv(y'jaF"~` L70n'{II#X #VIF5>chP#N8% ;cL7OP)R>PARuE# VDT<%ETV=<E578RHDq6cEIVG9xee ^pјBE>BDDbo~"Q}gF8 >CK 08i"IYѸh&Y}汬fGQ\%x5"x"`+YGy^Q{Q~Z!S- 8 +kI ڢvC;;3)0PO|Kfba' 7#NY22JM)H@%AFI"ZtE 1[nEeJAwEV8>T>.D3^Q$/ ,UYxNF0R_Z8d7$4VN1ꞓD*;7V ƀeBwCh !1@) (."DH Ah)M 1Q*"Qn4q= . @C#\bQODx%[ a$'3Q8؜ N(h{ W -İb\a20i2F@z QK` @r`HBl v0JyƜJ{+<]Dġ>j#XSX>n6dY['BXNX$ (@`8p6` 82 p(` l EalܚdHhANDI.dIzA)K)"bf)⸘'+(\}ǹXEa.LD2H89q(J/ f4b^ |0]`R !0"bQvp#\m Fv@^(@Q!BWKIiҎJSjBp"bxk :4C r!A Vn0CW sSÁPNp @P@ ! h@D `&AH@ Z lA)@`1"/ph64b-gA83D6G At*p7I<~> N6&DA1@aSRm]Z+@bTBaCi A14PB[ [ybR$ .>sjQMp\I X "0 A@(ڒ2ZKIHBLDB@^ő&(sf:У &B A)@<ic{1<*<,j=GWAl*Ȼb q<' T*CaUF4CHdjwlhT ,PޏzIIhR]L "<^ QF5 cRՆ8D  x8Ȁ5+Q4{ OPg B@E qGA0I0V OPi _ R읗6~M[E&@sݾ'(F 0 A?`#Ҧcx>Scz>+ @? K'@tdS,Hf J8o 1V6p3@LyGa>=s}zpA@!6ЩĜA!^!VDLBlHHT RF 0X!| @:&4aT//AjaȠHA !J` @bL p πM*o!JPr*a!̠ `v z,L!J!b!bPd`o+I\!vl!D a mZF5#dAjZ @J^  t=D*zqa6?!I VH>D.`N?ʛAaa|!` @8`.LnlaL p 펈i &ᦉ"*dA"& p@ ZB` tp F@ZAƭ$aAy8a=q~!B0H2!Fzba @ @ JZGnh4 oHA sXKf@`)=pi-)? Sqt!7~A>VA.!*aX!AZہ^ N`R`/ªĚ;=CLx PšAd.L I!LTAaTa `f@@T`zjh$FA8+E >`=gR-(A0a<%IB.q LBH<z$A @ h`^GӤT^LtjiSe5:=7!7rN 4AV.BX!PGTv ZV~ Np1j A=MƤffRpƣA~b!b!BIW@ g|HAaP!T  D@( LjbƖjQvB Aa^(^`uEdR$<@)`` 4:&"hApd8b[cBІcTRKTv[NV_7}8lRO4!DXa!0 RL b*ov"ߢIsbɃ"xA!b @ !Vlpadd `0,R@Ti+^v1!jYt@ ]|/A/vaA.)VEsuw~  Ad~nl6N@EL `q5* ayAFeQi}r7Wa$~!!F!T8A, x` OC/#A!!a Av 9a< \`  `6@ P<` VIUTƨ!&aiFa&A!+\DA0f& taxamrZAbbxcVC.1u JAN9S}c}V͓~@,2Il`L 6>Z`zArAAAxanӳa!'ZA6!4  :(J!aP~`6@<0.ն76a!z!R!~|ݭڵMEa_w++x !x*jh,." qx`nOv=4dO ffn8a"x.P rM 4kAXVajV]!~avap!!# Z x8(@arCj `*@`."@n~AևM4A~4  ӦXơYbCڒ ,<AHa=2  @\G&J̓/*MeqN[O:A*myh6va6a_ytA!!ɺ[vw:av@`a <ļsY&  At!vOD!! U4C PIF~EqwݱuoVuzC!/w{_wzMf]Dw9&z9QDza.T)UdlY,kءFPAU& dY(G"~8I {N(_JHDjb4ud9'h%YCX5gRrYE,G!6UfVPZuA5zPiHV0AEqgg:u'g9Mb0 ("0}' &2(P @4=TcV5Mc\6CZ6!(P Tpairtx_tbEٌy=ٌzYMƱLay?f9Fy4ij)BB@HX `xX@0*{E v6ExdAF$vj= 5t(8Gb6(k AQ#9_Mj#m p:FѪ:@"0^ p L A2!,piMQt(Epn!%lr;EPbb10)pB `bP `d@Bl1NC,bَ#{[[n<$  p0RB@M 6!v AE@%h&>BWc9WVJ(hBp/XG@EWxKMxO Zsv}HwP^\`G2t2(/rጉ.X ?P8$ }>'1eq<%28[*MFDGIPTJU:qHM)dMBHC)@CS-PL&n>oHks`J104d*\#W9T iF‘yN+C ~2;زZEcbAr_"Ȕ g#Ӭ}PɶB)*E%]#RS*Goi u2KsA:L<ގd z<@4gmf,KB* $ ""0*ˆ, c6)1E@LE!2TDTV%JMG,nAA IYAID$YM+0 0t B0(2~z, ͜'18& "? 9I*Pd ^$BEAc ZA,QDFhD1\7$4cHAi6,0% i n|'DZ\=Pw3vg!7pjy@3v)b#j"&1 b9 9X2M4IVP*INT\M 1$pDMa%~힍ej3 r!@ Ñ7H3Z) PbAA>!=Pc! $h*YCA:P({"H! AD"};`CXbueOGpAw{)>d|׀ 8&~^K в a9!aL) 6'HL 2r(^QY " J sB){NN E9  @ '!W-Ir& Ah8 px< 2&b8]1/ȼbZA,fC BpIÁA$\jA6iQ9+u)*`uq#l}Pldj/@p8?{ 7Àh$K!1fQ@(E(pU qBDXdNrFPi=k9SdMv'HV <@" т1B` j."] p3"[[+E M Kq p$ىQ#p?JE7eQ0(Bb!T.@л#4{c*P]!F m[A)EkB4B{ !KQn$%@`1pƀC4 FZ1DЦ9 Cӛa %~0{5T@Ʃ[ݯU LH(A@b nPX AG`N`1`~ Jbt\ +İlEd0p>l$bn4D+" BoT Z*(BYN $#Đ:0g a=``tX.~xd|8df:FV !r  ` *kj ^;j>ʨ0L VF!4A0|@tnfJ`LIW B`D`,`NvLi8#h$fRAd.5`h`Jʼ`| @ T( R vƮF`D @ @ $ PAx"8!!. oJ Z~08@-x'y0S[װJv'da*&QqLQڀ]d&! !l"Kȡ!: A3 !f^/fP! B@ ^Xx@ `?@`@b@8/M`DJ. ,`NZj b@a  AA*Ap~a,+!.A a4@ "  2P!?MPv0Ꞩ 1K2 2`T~e_t+Fs 0^L!#@hz`6FP0D`<З%ZN=(a,:+AaA(sa (2Qpp2A?!"AA~8ҁ ` >\l\6 CC0B"x+C!xAL!s4Aa,,8a(aANf6s@  t @ `!TAPva6y3!~   Sa:p4aa?A0jr!za, ` . ޑ,x1,6\=U> lj0r!3w3aǎ4~2+cni8aa`T^t` `VN@ [Gh+ /P63@"PawsB`  `<R8(@@R zLnj3PIBefvifmtUEe\'0 h*va4ЮA0Lh(aJa!jҰ F`|X 5DiT@A|` `rPr!*aA`baAAZXiR@ i^ ў%0T3vYWwswwfwmt?P4Pu<(kFAP ]aABZJ`r 62fvxF#fekOs]AF   eaz!/!!!A~A<! @ AARn6gUWnU]MohftLAH*bjax XR` P`H@l d dI#gewpH+f$@ m"h0rA!~l "d `Re @\y8TYY e wWB!4 `a0 ` ` 1@ 2`tPs* (fl8 snyok@ !  ( š sn` R : 2!Xa헅Zq0:f(A`;X `v@<@ f@34 &``8 (`]`[@`J@F j`)Hb1v~f!an 7J> U8@y`j4@& b@0&Y,\NP65 tI*姳xQs)S9&z > 2j` 81`-{&""8 H-VBeQ2 Bj6`G+۠  ``BR2.:gaك\E" `@ @`B<& 4 * $62*@:r* xpZOl@ G vN@00`2  `97|30\@>.@v` Py+d|G)İTZZ!tDk1aH!^FX F^dVj=*~ܲ2 v|=TP'Q48F>D!DaNHdL76FA:&H\A4@mgӶk]E V,, fxP%ՃhF}/R0UN?[Iڡf4Evvfx]B S;ay>0>C terra/inst/ex/lux.prj0000644000175000017500000000022114201035747014435 0ustar nileshnileshGEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]terra/inst/ex/meuse.tif0000644000175000017500000001556114201035747014747 0ustar nileshnileshII*Ps3=S P hH (`F p7G|w  1736 -9999 138 -9999 test D@D@AbA#      )#     J@y5@b0>?A`BAmtr@@TXAunknown|WGS 84|-32768($ APd. CQN-EQn=GR$M%IRd]-KSm5MS}=OT%EQTe.G*mVBx#@TլRX $WB{a=kd&CAG l "H ^T7W'`4 K@!h |6I9LZ77 B^OP &@$Mf[EM`#('(v:G\0 O`4~]lLR *@&.H n` #1""sO$pUf(F8X2@ @DvD2:c cxFxQ$8;F@@bV@,H VP>"i ®!!D.L<̂J#@ ! !(o1"B8ΩAFK#5W O@"!Ue 3@,  /'xo S`x6uZZ"@F% :xp SȩB^vz&B }14  ! @`;5i q8y4Um`R}@a6xVӨ !` 4 m`ybO b`vvPz7@@ii 4ǝ@ zO&L!WP@ⷘ@` _T  Nͣ'Xv]U5OrgXƸkpm/bb$VʜǢG0)DA~e(.1h.y9+ZP,:&\#d='n\JIbd_"Y*`Xv!DVH‚g 18jBU[Nb1K-WCeP iĴ@ %4u ;7 QʀhMـRf0P 3uX|?0# pad{r1/}G R2jܚL2 nc `$@PQR9cgqb<.DP @b&h uX;iqn-0/]h@s``5{pE$i0E : qu0 "!S06l-@xs! Q2GFBZ?@  ,`(@0iūD\7B[+pP%Ӊ )@EQPZ;@R`3d.:`F>e;5w:|GNal(p(xZ; ) sRl9댋—UUčq Z@$ YK( 1!B2%AJ ŭ}qVj[<./ ;QPkbA |` E A\@ahs5!@7НڥqD=0 1ȆBPJ`>+#Z5ߖPTA4G_ˌoaѺmh`NPU4@OjuCB&E[fwo2̶6ť$^m!($ APd.[FA"4"@kZ`,, 8@%p l@' @(M)mVVUUH.G`JڠH^!`sY`dX(C0MCөYm"[gZ9*l D1e"Dc*0 D`I$|Ԍ2i<>80lj` XPp8lW ! | -`jkC$=+g7#PX>f0[$7!x!0#h2"P'pvk"BC,;-KD$Hٶ@ I B8T N͂ "۩"րx 3, K̽M<A0mN3P$T@ 3JF 2!&"x !KY pAɽ{(.S5-` (# ZO.!r!!gZ"3IZXm 8ȑ+HKqyy!@@`A,h hz#Z@25EYDIzc 8e/ t btt""~r FY+3*Bw1Unzhshjƿ•4MiJ&FV ,uW3 p|P/n gOhIOX[Y}[`x]42'~8(\.ޡ%S~u"v v ]Fc qAg(1( 8I E``%跑rDW$ Gy xn)@y>ʖ\(F !zR'>P5 滰tTSb_154a$ĸ+gN> J8o9+|^G%$CPX o!JsE'PO>Q+A wON18j50l |OLf1+sb j0-`+6Šo~6-xxݓbc y^ uMS4!0 @i?t94l͙QD$QϘ6', x#LC  V(Z{y,QJdIvؿldA"7”#KZ\!z@A hD6_cI ` # bGL:s2D  p%(Eg(3`hL)^@G3O{2.+XHHì]!|1 JajA(f5I6خ$MXk pV0 @|y㷀"ը? +\, 0o>-EPX-B'QbTE ::},d`*Tgf(5ܟ[xLYUP0 }l'Db_*Gŀ;8@jBQ.)@UZ.BgT\DtL:8V3H _XV`E{I0A%@ %sP2Xq(Måjܞ>:Lɡq[2BhDnlVbq%3'` &N`BO oz8`3"l'tgnCOQ"'p[ǾE\G(jTU =n(RP<@NLҌz@@Ad!:!6&z&\lHQxWæ1V1exH*(-0a>cd 6P up4 @/*v`T2FX(CRHĆ10c'OJ*IGOʄjAP/-cfC9cmi n@:A'B500JR.( Pg11cy30qUoyZ,d@F@&7` PB Fp!DptW|9e!p_솤xQ b#/j@lbJ LuDMҀ(@A//czhfttE'EWܥFx\' K4%Fa a`aE<@(Y$Q iRigS%#vU\0U`{x0dXWHĢ&fxp_&~%'C(ETh:aafT`ja@ sBiNJB_B;.=^2HfLy@GdsGyHN€*A^#v`@aRx *N8#.QT3W4Vz\lH2bmz(]P%xr>r-]Hv!Q`<  .Fހ4a%@S>3\?eZ*Ft\8OUA|1=Ĥn^:#FH@@P'Da bhvAL@`X˖p3R;<8%H%cdJ.K9ZU&]\%Iذa@Dn/ "hj#!L @$T!MFHbWRЄ\~v2.agHt_(kGG _gl';P?g;$?%#?f@8E)qpM08c FÐ(BgWa _$u\kbr0b;DlMZM6D8BS4!1-oE/&c\2HȆ9gy șIL裖^6Op2@F3"=l͗RAtN# =8\1#Pexx> s`-']p8J~z\-q%c\EX8g\*D&]yK:(jfi@>1g 7bOĄJ" ! ` <)p Y#`4/"D=& *HPP*%EQTe.M @q] xxV,&<L@F`ut*IC@ ('rU[B!>@! c@) ʹvSP Fͨ&: A;&v-8BNF`C[HAf pK%c%hޝ1:L>C WGmCL̙ DU% H ΋" GslX*DXYE1Bh`p!D}'`? 547 -9999 141 -9999 elevation ??wwwww@I@#  mtr@@TXAunknown|-32768($ APd. CQN-EQn=!.cTY/F\ 9(Pf4*%AyM)N @A. t[kh:-gV\ wS@(AްYnXVV+66яFX 0`:%d6YbX@@e\xE+ cm{26aaW\ 3.` 3Zӭ] ?]GK~8s:@({0-ـ׀%l&Ͱʼ{+. n۾ϳ)[T޷భo°ocLhD1|-Alp2c1k .+늒$5Q̣X%۲e1e@SokLQ웮KU gv <`k2A4)MjjLPU +lH2ڸ睎` /(42*EauO$ɫXF~5 -Z+k|H$EQ؎6m-VNS0lJ⸬e$Yѫ,]7F/ɚҍjoɼˋJ7L$& V\N\Zj놭Ajs2լBO@.L$U$[y2~&! _rh@ T .8_O~۵z[MCH7.9mSgu5c4:ږͣ[֦ܐ6QA H`W3=0$sD(jKZjpհT7ޥ-wwRڭ6B()$HE#PҌ%/2(W(1x|N7!2Pԣ:qˊ*B` @@[v/|Pe #n]@?OR"kN|$ەfY37Y9<j!0@ gjB~ _B8Cak %+0E_ Oy['l#@ V (;!9>ƨSqo-,AEM))1럗O08CccAp#X LLAķsJy@M 66+Hx:#h/u0DF76(MH2f{A2I<)<Ę ny.nвCqYC" Oh ̿!-Dvb`Yh#xAl;:Du.e+'vԌJ @`=E RD5fM3VT<%%$0Бm_HD_!7 rBPܙvpO<(xBzu 7YZhx+`aVSuEV Y[ Adcbq_&Û6#6&.mgo0&7NH<avvՀY% ¾@O1/MxYJ08'I t f@%GĘs& [Pno A$kPgnÛoV`J$(xVa9`Nռo&;dv{@0xƔC12Zrj k8fcD˘}tߒ x#>\K@S`Ļ3 $ )8-\m2o̗ńe[9rp?: bIj€|1]N͆A¸t#X7|Kؠ;)cxN ;:wݩuT}n~ nSs"ġSOZ-15F<\ 7 9hP/@&:[$`%"v|+m~2( g@͕Dty-n$d2t+ %p U` pvD79e!KnX2WkL8Z3nVLnf~ @ w 6ؓC{V-ƝXOr6v5z_ )/eܭ{*Q23fa-ը`a[PdS8Fr b0xe0|Dj`G!qYa԰h<M<[͹Pǘ(c0);ω[o   + nCH Bojij(婂8m'Gd.+ eBC00d5N<8d<$pi"j0>ję&',ԿLMx8io'Hvg8C5D>BD&bP¶V#Ni$ 8N8I$AȮDt|Ir| *n{ܼZPp.࿧| X-HK(~1J'jH' $Bj~m4h)#J/Ö9( 2fĚ#dHG `H~vx` G.KXMDJr)8jJm)": m(nšC  `. . $.@ d@* ( ' f$ O@'9M,@SOk4|F5`f@OR0#`Z`8K희dP,O-eÂ@, ,@.|cUc1% .Kd% v@&.R` P4@$@$! P` T%"8'Kp,,` ZJҡ` PQ"0ؾF˸"ێm?`jH J@M !&!lK9΢p3"0h8 dL`Xt@'` b! "H\%-Hxk"-^%HN?-(.ȱ '#0K h ') !B ޑ溮Oh k>"x oPzcsFI{U&̿6ؓ l` 7dCS#Km28,v!t6 ^i)]~A@=$C#h+@Cxdj±'P4ne? q`,[j>Md_ϣJc7<Kr`"bМ/ؐ^$𲓣RsiE Q&(s?wu?B= dfIeV-%H?82dLI7iҔӂ[@-!8cr0bRU=%ҦVdWE;fW2`L$"~X`"(8YmZǤ};wFj@ x-I47X^)|=|RE~)MFdT 8\X( -oƁ;NaiI s%TZWpB)<)I!Rx)py`cQ a8g+N*ådW=le}}7Z4>!sz^QH/+ҡΑ'|&C[RJxhqeY# 'Ɉ"LDW$|;їOPKrPPe6xǓBKq04cO., &"xY.K0 |sAr2/LHBBp/<<VRoJ/"~VA((DJ0>h$iFdY dJN(f'ļY tk&9Pyd0=0$̆:@DL jJjz+d(<' ~㨗 j@aXhnF",8sNFn;xc`"'¾LDLOp(8x\Vg|W'4s–&&~%f%8pp_;~Q<*dJ1t~%zς, LGV bL j)+'C(XFp<HCiQjxf0ƀ$^#FbiC.xkVn O)]BsA_vBH'F00@j="dLq/̂0"|= N8]B;,XE0H,dZ.D~Y9/12GHN^(\wpx@e`'rOK$>ErOL @E'1c8"+KDYfD LC*',"+Dē^K8Znh;;F3B8#:@8#.',tL̳KVB ,nAfJmH!c>@;/ *u(@b%] KR@B@H}Sf)8ȚrmE>WYŢ-e],]v gs jyb?uuW0#i򂆫JmX}EcY]KQ!~EXøhAm|Y~]CA'ꕎt0K#JAf"̫m9F|-$XRD]K^>KKrKc -iXh h&2O@xYFuDdZ%$돘2X.&08¿_W҅YQ; sԒ n +\LD,;;2*JṰEWPd* @p9jj \Y DF"1VgNyˠwwOp'82Sf<NR1VYDء0iZF%š+I jc,$5JH2 sǒ*p($ APd.f* *3K@P9ƀ#P ,x 6]aO1 @}0OT$XhRr%RrQ[j:]WV‡`]c[Wu]W4terra/inst/ex/lux.shx0000644000175000017500000000030414201035747014446 0ustar nileshnilesh' b@ QH@Kŭ@ڿ_?I@2 p  "VH' x3; 8AF `J hT b r Xterra/cleanup0000755000175000017500000000011614203000630013060 0ustar nileshnilesh#!/bin/sh rm -fr src/Makevars config.log config.status rm -fr proj_conf_test* terra/NAMESPACE0000644000175000017500000000577414201035747012760 0ustar nileshnileshuseDynLib(terra, .registration=TRUE) import(methods, Rcpp) importFrom(stats, na.omit) exportMethods("[", "[[", "!", "%in%", activeCat, "activeCat<-", "add<-", adjacent, all.equal, aggregate, align, animate, app, area, Arith, approximate, as.bool, as.int, as.contour, as.lines, as.points, as.polygons, as.raster, as.array, as.data.frame, as.factor, as.list, as.logical, as.matrix, as.numeric, atan2, atan_2, autocor, barplot, boundaries, boxplot, buffer, cartogram, categories, cats, catalyze, clamp, classify, clearance, cellSize, cells, cellFromXY, cellFromRowCol, cellFromRowColCombine, centroids, click, colFromX, colFromCell, colorize, coltab, "coltab<-", Compare, compareGeom, contour, convHull, crds, cover, crop, crosstab, crs, "crs<-", datatype, deepcopy, delauny, densify, density, depth, "depth<-", describe, diff, disagg, direction, distance, dots, draw, erase, extend, ext, "ext<-", extract, expanse, fillHoles, fillTime, flip, focal, focal3D, focalCor, focalReg, focalCpp, focalValues, freq, gaps, geom, geomtype, global, gridDistance, hasMinMax, hasValues, hist, head, ifel, impose, init, image, inext, inMemory, inset, interpolate, intersect, is.bool, is.int, is.lonlat, isTRUE, isFALSE, is.factor, is.lines, is.points, is.polygons, is.related, is.valid, lapp, layerCor, levels, linearUnits, lines, Logic, varnames, "varnames<-", longnames, "longnames<-", makeValid, mask, match, math, Math, Math2, mean, median, merge, mergeLines, mergeTime, minmax, minRect, modal, mosaic, na.omit, NAflag, "NAflag<-", nearby, nearest, ncell, ncol, "ncol<-", nlyr, "nlyr<-", nrow, "nrow<-", nsrc, origin, "origin<-", pairs, patches, perim, persp, plot, plotRGB, RGB, "RGB<-", polys, points, predict, project, quantile, query, rapp, rast, rasterize, readStart, readStop, readValues, rectify, relate, removeDupNodes, res, "res<-", resample, rescale, rev, rotate, rowFromY, rowColFromCell, rowFromCell, sapp, scale, sds, sprc, src, sel, selectRange, setMinMax, setValues, segregate, selectHighest, setCats, set.cats, set.crs, set.ext, set.names, set.values, size, sharedPaths, shift, simplifyGeom, snap, sources, spatSample, split, spin, stdev, stretch, subst, summary, Summary, subset, svc, symdif, t, tail, tapp, terrain, tighten, makeNodes, makeTiles, time, "time<-", text, trans, trim, units, union, "units<-", unique, vect, values, "values<-", voronoi, vrt, weighted.mean, which.lyr, which.min, which.max, which.lyr, width, window, "window<-", writeCDF, writeRaster, wrap, writeStart, writeStop, writeVector, writeValues, xmin, xmax, "xmin<-", "xmax<-", xres, xFromCol, xyFromCell, xFromCell, ymin, ymax, "ymin<-", "ymax<-", yres, yFromCell, yFromRow, zonal, zoom, cbind2, RGB2col) S3method(cbind, SpatVector) S3method(rbind, SpatVector) S3method(as.data.frame, SpatRaster) S3method(as.data.frame, SpatVector) S3method(as.matrix, SpatRaster) S3method(as.list, SpatRaster) S3method(as.list, SpatVector) export(focalMat, gdal, arrow, north, sbar, terraOptions, tmpFiles, makeVRT, mem_info, free_RAM, shade, gdalCache, fileBlocksize, vector_layers) terra/configure.ac0000644000175000017500000005037414202054726014022 0ustar nileshnileshdnl Process this file with autoconf to produce a configure script. dnl GDAL stuff largely copied from rgdal, (c) Roger Bivand AC_INIT AC_CONFIG_SRCDIR([src/write_ogr.cpp]) : ${R_HOME=`R RHOME`} if test -z "${R_HOME}"; then echo "could not determine R_HOME" exit 1 fi RBIN="${R_HOME}/bin/R" # https://github.com/r-spatial/sf/issues/1054: # RVER=`"${RBIN}" --version | head -1 | cut -f3 -d" "` RSCRIPT="${R_HOME}/bin/Rscript" RVER=`"${RSCRIPT}" -e 'writeLines(paste(sep=".", base::version$major, base::version$minor))'` RVER_MAJOR=`echo ${RVER} | cut -f1 -d"."` RVER_MINOR=`echo ${RVER} | cut -f2 -d"."` RVER_PATCH=`echo ${RVER} | cut -f3 -d"."` if test [$RVER_MAJOR = "development"]; then CXX11=`"${RBIN}" CMD config CXX11` CXX11STD=`"${RBIN}" CMD config CXX11STD` else if test [$RVER_MAJOR -lt 3] -o [$RVER_MAJOR -eq 3 -a $RVER_MINOR -lt 3]; then AC_MSG_ERROR([terra is not compatible with R versions before 3.3.0]) else if test [$RVER_MAJOR -eq 3 -a $RVER_MINOR -eq 3]; then CXX11=`"${RBIN}" CMD config CXX1X` CXX11STD=`"${RBIN}" CMD config CXX1XSTD` else CXX11=`"${RBIN}" CMD config CXX11` CXX11STD=`"${RBIN}" CMD config CXX11STD` fi fi fi # pick all flags for testing from R : ${CC=`"${RBIN}" CMD config CC`} : ${CXX=${CXX11} ${CXX11STD}} : ${CFLAGS=`"${RBIN}" CMD config CFLAGS`} : ${CPPFLAGS=`"${RBIN}" CMD config CPPFLAGS`} : ${CXXFLAGS=`"${RBIN}" CMD config CXXFLAGS`} : ${LDFLAGS=`"${RBIN}" CMD config LDFLAGS`} # AC_SUBST([CC],["clang"]) # AC_SUBST([CXX],["clang++"]) AC_MSG_NOTICE([CC: ${CC}]) AC_MSG_NOTICE([CXX: ${CXX}]) # AC_MSG_NOTICE([${PACKAGE_NAME}: ${PACKAGE_VERSION}]) #GDAL GDAL_CONFIG="gdal-config" GDAL_CONFIG_SET="no" AC_ARG_WITH([gdal-config], AS_HELP_STRING([--with-gdal-config=GDAL_CONFIG],[the location of gdal-config]), [gdal_config=$withval]) if test [ -n "$gdal_config" ] ; then GDAL_CONFIG_SET="yes" AC_SUBST([GDAL_CONFIG],["${gdal_config}"]) AC_MSG_NOTICE(gdal-config set to $GDAL_CONFIG) fi if test ["$GDAL_CONFIG_SET" = "no"] ; then AC_PATH_PROG([GDAL_CONFIG], ["$GDAL_CONFIG"],["no"]) if test ["$GDAL_CONFIG" = "no"] ; then AC_MSG_RESULT(no) AC_MSG_ERROR([gdal-config not found or not executable.]) fi else AC_MSG_CHECKING(gdal-config exists) if test -r "${GDAL_CONFIG}"; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) AC_MSG_ERROR([gdal-config not found - configure argument error.]) fi AC_MSG_CHECKING(gdal-config executable) if test -x "${GDAL_CONFIG}"; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) AC_MSG_ERROR([gdal-config not executable.]) fi fi AC_MSG_CHECKING(gdal-config usability) if test `${GDAL_CONFIG} --version`; then GDAL_CPPFLAGS=`${GDAL_CONFIG} --cflags` GDAL_VERSION=`${GDAL_CONFIG} --version` GDAL_LIBS=`${GDAL_CONFIG} --libs` GDAL_DEP_LIBS=`${GDAL_CONFIG} --dep-libs` GDAL_DATADIR=`${GDAL_CONFIG} --datadir` AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) echo "Error: gdal-config not found" echo "The gdal-config script distributed with GDAL could not be found." echo "If you have not installed the GDAL libraries, you can" echo "download the source from http://www.gdal.org/" echo "If you have installed the GDAL libraries, then make sure that" echo "gdal-config is in your path. Try typing gdal-config at a" echo "shell prompt and see if it runs. If not, use:" echo " --configure-args='--with-gdal-config=/usr/local/bin/gdal-config'" echo "with appropriate values for your installation." echo "" exit 1 fi AC_MSG_NOTICE([GDAL: ${GDAL_VERSION}]) AC_MSG_CHECKING([GDAL version >= 2.0.1]) GDAL_MAJ_VER=`echo $GDAL_VERSION | cut -d "." -f1` if test ${GDAL_MAJ_VER} -lt 2 ; then AC_MSG_RESULT(no) AC_MSG_ERROR([terra is not compatible with GDAL versions below 2.0.1]) else AC_MSG_RESULT(yes) fi INLIBS="${LIBS}" INCPPFLAGS="${CPPFLAGS}" INPKG_CPPFLAGS="${PKG_CPPFLAGS}" INPKG_LIBS="${PKG_LIBS}" AC_SUBST([PKG_CPPFLAGS], ["${INPKG_CPPFLAGS} ${GDAL_CPPFLAGS}"]) AC_SUBST([PKG_LIBS], ["${INPKG_LIBS} ${GDAL_LIBS}"]) # honor PKG_xx overrides # for CPPFLAGS we will superfluously double R's flags # since we'll set PKG_CPPFLAGS with this, but that shouldn't hurt CPPFLAGS="${INCPPFLAGS} ${PKG_CPPFLAGS}" gdalok=yes AC_CHECK_HEADERS(gdal.h,,gdalok=no) if test "${gdalok}" = no; then AC_MSG_ERROR([gdal.h not found in given locations.]) fi NEED_DEPS=no LIBS="${INLIBS} ${PKG_LIBS}" [cat > gdal_test.cpp <<_EOCONF #include #ifdef __cplusplus extern "C" { #endif int main() { GDALAllRegister(); } #ifdef __cplusplus } #endif _EOCONF] AC_MSG_CHECKING(GDAL: linking with --libs only) ${CXX} ${CPPFLAGS} -o gdal_test gdal_test.cpp ${LIBS} 2> errors.txt if test `echo $?` -ne 0 ; then gdalok=no AC_MSG_RESULT(no) else AC_MSG_RESULT(yes) fi if test "${gdalok}" = no; then AC_MSG_CHECKING(GDAL: linking with --libs and --dep-libs) LIBS="${LIBS} ${GDAL_DEP_LIBS}" gdalok=yes ${CXX} ${CPPFLAGS} -o gdal_test gdal_test.cpp ${LIBS} 2>> errors.txt if test `echo $?` -ne 0 ; then gdalok=no fi if test "${gdalok}" = yes; then NEED_DEPS=yes AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi fi if test "${gdalok}" = no; then cat errors.txt AC_MSG_NOTICE([Install failure: compilation and/or linkage problems.]) AC_MSG_ERROR([GDALAllRegister not found in libgdal.]) fi rm -f gdal_test errors.txt gdal_test.cpp GDAL_GE_250="no" GDAL_MAJ_VER=`echo $GDAL_VERSION | cut -d "." -f1` GDAL_MOD_VER=`echo $GDAL_VERSION | cut -d "." -f2` if test "${GDAL_MAJ_VER}" = 2 ; then if test "${GDAL_MOD_VER}" -ge 5 ; then GDAL_GE_250="yes" fi else if test "${GDAL_MAJ_VER}" -ge 3 ; then GDAL_GE_250="yes" fi fi GDAL_DATA_TEST_FILE="${GDAL_DATADIR}/pcs.csv" AC_MSG_CHECKING(GDAL: ${GDAL_DATADIR}/pcs.csv readable) if test -r "${GDAL_DATA_TEST_FILE}" ; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) if test "${GDAL_GE_250}" = "no" ; then AC_MSG_ERROR([pcs.csv not found in GDAL data directory.]) fi fi # Optional local copy of GDAL datadir and PROJ_LIB data_copy=no if test "${PROJ_GDAL_DATA_COPY}" ; then data_copy=yes AC_MSG_NOTICE([PROJ_GDAL_DATA_COPY used.]) else AC_ARG_WITH([data-copy], AS_HELP_STRING([--with-data-copy=yes/no],[local copy of data directories in package, default no]), [data_copy=$withval]) fi if test "${data_copy}" = "yes" ; then AC_MSG_NOTICE([Copy data for:]) proj_lib0="${PROJ_LIB}" AC_ARG_WITH([proj-data], AS_HELP_STRING([--with-proj-data=DIR],[location of PROJ data directory]), [proj_lib1=$withval]) if test -n "${proj_lib0}" ; then proj_lib="${proj_lib0}" else proj_lib="${proj_lib1}" fi if test -n "${proj_lib}" ; then if test -d "${proj_lib}" ; then cp -r "${proj_lib}" "${R_PACKAGE_DIR}" AC_MSG_NOTICE([ PROJ: ${proj_lib}]) else AC_MSG_ERROR([PROJ data files not found; set environment variable PROJ_LIB=DIR or --with-proj-data=DIR.]) fi else AC_MSG_ERROR([PROJ data files not found; set environment variable PROJ_LIB=DIR or --with-proj-data=DIR.]) fi if test -d "${GDAL_DATADIR}" ; then cp -r "${GDAL_DATADIR}" "${R_PACKAGE_DIR}" AC_MSG_NOTICE([ GDAL: ${GDAL_DATADIR}]) else AC_MSG_ERROR([GDAL data files not found.]) fi fi # # test whether PROJ is available to gdal: # gdal_has_proj=no [cat > gdal_proj.cpp <<_EOCONF #include #include #include int main(int argc, char *argv[]) { OGRSpatialReference *dest = new OGRSpatialReference; OGRSpatialReference *src = new OGRSpatialReference; src->importFromEPSG(4326); dest->importFromEPSG(3857); OGRCoordinateTransformation *ct = OGRCreateCoordinateTransformation(src, dest); return(ct == NULL); // signals PROJ is not available through gdal } _EOCONF] AC_MSG_CHECKING(GDAL: checking whether PROJ is available for linking:) ${CXX} ${CPPFLAGS} -o gdal_proj gdal_proj.cpp ${LIBS} 2> errors.txt if test `echo $?` -ne 0 ; then gdal_has_proj=no AC_MSG_RESULT(no) else gdal_has_proj=yes AC_MSG_RESULT(yes) fi if test "${gdal_has_proj}" = no; then cat errors.txt AC_MSG_NOTICE([Install failure: compilation and/or linkage problems.]) AC_MSG_ERROR([cannot link projection code]) fi AC_MSG_CHECKING(GDAL: checking whether PROJ is available fur running:) ./gdal_proj if test `echo $?` -ne 0 ; then gdal_has_proj=no AC_MSG_RESULT(no) else gdal_has_proj=yes AC_MSG_RESULT(yes) fi if test "${gdal_has_proj}" = no; then AC_MSG_ERROR([OGRCoordinateTransformation() does not return a coord.trans: PROJ not available?]) fi rm -fr errors.txt gdal_proj.cpp gdal_proj AC_MSG_NOTICE([GDAL: ${GDAL_VERSION}]) # sqlite3 AC_ARG_WITH([sqlite3-lib], AS_HELP_STRING([--with-sqlite3-lib=LIB_PATH],[the location of sqlite3 libraries]), [sqlite3_lib_path=$withval]) if test [ -n "$sqlite3_lib_path" ] ; then AC_SUBST([SQLITE3_LIBS], ["-L${sqlite3_lib_path}"]) fi # # PROJ # PROJ_CONFIG="pkg-config proj" if `$PROJ_CONFIG --exists` ; then AC_MSG_NOTICE([pkg-config proj exists, will use it]) proj_config_ok=yes else proj_config_ok=no fi AC_ARG_WITH([proj-include], AS_HELP_STRING([--with-proj-include=DIR],[location of proj header files]), [proj_include_path=$withval]) if test [ -n "$proj_include_path" ] ; then AC_SUBST([PROJ_CPPFLAGS],["-I${proj_include_path}"]) else if test "${proj_config_ok}" = yes; then PROJ_INCLUDE_PATH=`${PROJ_CONFIG} --cflags` AC_SUBST([PROJ_CPPFLAGS],["${PROJ_INCLUDE_PATH}"]) fi fi # honor PKG_xx overrides # for CPPFLAGS we will superfluously double R's flags # since we'll set PKG_CPPFLAGS with this, but that shouldn't hurt AC_ARG_WITH([proj-api], AS_HELP_STRING([--with-proj-api=yes/no],[use the deprecated proj_api.h even when PROJ 6 is available; default no]), [proj_api=$withval]) PROJ6="no" PROJH="no" if test "${proj_config_ok}" = yes; then PROJ_VERSION=`${PROJ_CONFIG} --modversion` PROJV1=`echo "${PROJ_VERSION}" | cut -c 1` if test "${PROJV1}" -ge 6; then PROJ6="yes" PROJ_CPPFLAGS="${PROJ_CPPFLAGS} -DHAVE_PROJ_H" if test "${proj_api}" = yes; then AC_MSG_NOTICE([using proj_api.h even with PROJ 5/6]) PROJ_CPPFLAGS="${PROJ_CPPFLAGS} -DACCEPT_USE_OF_DEPRECATED_PROJ_API_H" else AC_MSG_NOTICE([using proj.h.]) PROJH="yes" fi fi else if test "${PROJH}" = no ; then PROJH=yes AC_CHECK_HEADERS(proj.h,,PROJH=no) if test "${PROJH}" = yes; then PROJ6="yes" PROJ_CPPFLAGS="${PROJ_CPPFLAGS} -DHAVE_PROJ_H" fi fi fi CPPFLAGS="${INCPPFLAGS} ${PKG_CPPFLAGS} ${PROJ_CPPFLAGS}" if test "${PROJH}" = no then proj4ok=yes AC_CHECK_HEADERS(proj_api.h,,proj4ok=no) if test "${proj4ok}" = no; then AC_MSG_ERROR([proj_api.h not found in standard or given locations.]) fi fi # dnl ditto for a library path AC_ARG_WITH([proj-lib], AS_HELP_STRING([--with-proj-lib=LIB_PATH],[the location of proj libraries]), [proj_lib_path=$withval]) if test [ -n "$proj_lib_path" ] ; then AC_SUBST([PROJ_LIBS], ["-L${proj_lib_path} ${INPKG_LIBS} -lproj"]) else if test "${proj_config_ok}" = yes; then if test `uname` = "Darwin"; then PROJ_LIB_PATH=`${PROJ_CONFIG} --libs --static` else PROJ_LIB_PATH=`${PROJ_CONFIG} --libs` fi AC_SUBST([PROJ_LIBS], ["${PROJ_LIB_PATH} ${INPKG_LIBS}"]) proj_version=`${PROJ_CONFIG} --modversion` AC_MSG_NOTICE([PROJ: ${proj_version}]) else PROJ_LIBS="${PKG_LIBS} -lproj" fi fi LIBS="${PROJ_LIBS} ${INLIBS} ${PKG_LIBS}" if test "${PROJH}" = no; then proj4ok=yes AC_CHECK_LIB(proj,pj_init_plus,,proj4ok=no) if test "${proj4ok}" = no; then AC_MSG_ERROR([libproj not found in standard or given locations.]) fi [cat > proj_conf_test.c <<_EOCONF #include #include #include int main() { printf("%d\n", PJ_VERSION); exit(0); } _EOCONF] else [cat > proj_conf_test.cpp <<_EOCONF #include #include #include int main() { proj_context_create(); exit(0); } _EOCONF] #AC_CHECK_LIB(proj,proj_context_create,,proj6ok=no) AC_MSG_CHECKING(PROJ: checking whether PROJ and sqlite3 are available for linking:) ${CXX} ${CPPFLAGS} -o proj_conf_test proj_conf_test.cpp ${LIBS} $SQLITE3_LIBS -lsqlite3 2> errors.txt if test `echo $?` -ne 0 ; then proj6ok=no AC_MSG_RESULT(no) else proj6ok=yes AC_MSG_RESULT(yes) fi if test "${proj6ok}" = no; then AC_MSG_ERROR([libproj or sqlite3 not found in standard or given locations.]) fi [cat > proj_conf_test.c <<_EOCONF #include #include #include int main() { printf("%d.%d.%d\n", PROJ_VERSION_MAJOR, PROJ_VERSION_MINOR, PROJ_VERSION_PATCH); exit(0); } _EOCONF] fi #AC_MSG_NOTICE([PKG_LIBS: ${PKG_LIBS}]) ${CC} ${CFLAGS} ${CPPFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS} proj_version=`./proj_conf_test` AC_ARG_WITH([proj-share], AS_HELP_STRING([--with-proj-share=SHARE_PATH],[the location of proj metadata files]), [proj_share_path=$withval]) if test [ -n "$proj_share_path" ] ; then AC_MSG_NOTICE([PROJ_LIB: ${proj_share_path}]) fi if test ${PROJ6} = "no"; then [cat > proj_conf_test.c <<_EOCONF #include #include #if PJ_VERSION <= 480 FILE *pj_open_lib(projCtx, const char *, const char *); #endif int main() { #if PJ_VERSION <= 480 FILE *fp; #else PAFile fp; #endif projCtx ctx; ctx = pj_get_default_ctx(); fp = pj_open_lib(ctx, "epsg", "rb"); if (fp == NULL) exit(1); #if PJ_VERSION <= 480 fclose(fp); #else pj_ctx_fclose(ctx, fp); #endif exit(0); } _EOCONF] ${CC} ${CFLAGS} ${CPPFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS} if test [ -n "$proj_share_path" ] ; then PROJ_LIB="${proj_share_path}" ./proj_conf_test proj_share=`echo $?` else ./proj_conf_test proj_share=`echo $?` fi AC_MSG_CHECKING(PROJ: epsg found and readable) if test ${proj_share} -eq 1 ; then AC_MSG_RESULT(no) STOP="stop" else AC_MSG_RESULT(yes) fi rm -f proj_conf_test.c proj_conf_test if test "$STOP" = "stop" ; then echo "Error: proj/epsg not found" echo "Either install missing proj support files, for example" echo "the proj-nad and proj-epsg RPMs on systems using RPMs," echo "or if installed but not autodetected, set PROJ_LIB to the" echo "correct path, and if need be use the --with-proj-share=" echo "configure argument." exit 1 fi else # proj >= 6 if test "${PROJH}" = no; then [cat > proj_conf_test.c <<_EOCONF #include #include int main() { PAFile fp; projCtx ctx; ctx = pj_get_default_ctx(); fp = pj_open_lib(ctx, "proj.db", "rb"); if (fp == NULL) exit(1); pj_ctx_fclose(ctx, fp); exit(0); } _EOCONF] ${CC} ${CFLAGS} ${CPPFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS} if test [ -n "$proj_share_path" ] ; then PROJ_LIB="${proj_share_path}" ./proj_conf_test proj_share=`echo $?` else ./proj_conf_test proj_share=`echo $?` fi AC_MSG_CHECKING(PROJ: proj.db found and readable) if test ${proj_share} -eq 1 ; then AC_MSG_RESULT(no) STOP="stop" else AC_MSG_RESULT(yes) fi rm -f proj_conf_test.c proj_conf_test if test "$STOP" = "stop" ; then echo "Error: proj/proj.db not found" echo "Either install missing proj support files, set PROJ_LIB to the" echo "correct path, and if need be use the --with-proj-share=" echo "configure argument." exit 1 fi [cat > proj_conf_test.c <<_EOCONF #include #include #if PJ_VERSION <= 480 FILE *pj_open_lib(projCtx, const char *, const char *); #endif int main() { #if PJ_VERSION <= 480 FILE *fp; #else PAFile fp; #endif projCtx ctx; ctx = pj_get_default_ctx(); fp = pj_open_lib(ctx, "conus", "rb"); if (fp == NULL) exit(1); #if PJ_VERSION <= 480 fclose(fp); #else pj_ctx_fclose(ctx, fp); #endif exit(0); } _EOCONF] ${CC} ${CFLAGS} ${CPPFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS} if test [ -n "$proj_share_path" ] ; then PROJ_LIB="${proj_share_path}" ./proj_conf_test proj_share=`echo $?` else ./proj_conf_test proj_share=`echo $?` fi AC_MSG_CHECKING(PROJ: conus found and readable) if test ${proj_share} -eq 1 ; then WARN="warn" AC_MSG_RESULT(no) else AC_MSG_RESULT(yes) fi rm -f proj_conf_test.c proj_conf_test if test "$WARN" = "warn" ; then echo "Note: proj/conus not found" echo "No support available in PROJ4 for NAD grid datum transformations" echo "If required, consider re-installing from source with the contents" echo "of proj-datumgrid-1..zip from http://download.osgeo.org/proj/ in nad/." fi fi # PROJH = no fi # proj >= 6 # # GEOS: # GEOS_CONFIG="geos-config" GEOS_CONFIG_SET="no" AC_ARG_WITH([geos-config], AS_HELP_STRING([--with-geos-config=GEOS_CONFIG],[the location of geos-config]), [geos_config=$withval]) if test [ -n "$geos_config" ] ; then GEOS_CONFIG_SET="yes" AC_SUBST([GEOS_CONFIG],["${geos_config}"]) AC_MSG_NOTICE(geos-config set to $GEOS_CONFIG) fi if test ["$GEOS_CONFIG_SET" = "no"] ; then AC_PATH_PROG([GEOS_CONFIG], ["$GEOS_CONFIG"],["no"]) if test ["$GEOS_CONFIG" = "no"] ; then AC_MSG_RESULT(no) AC_MSG_ERROR([geos-config not found or not executable.]) fi else AC_MSG_CHECKING(geos-config exists) if test -r "${GEOS_CONFIG}"; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) AC_MSG_ERROR([geos-config not found - configure argument error.]) fi AC_MSG_CHECKING(geos-config executable) if test -x "${GEOS_CONFIG}"; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) AC_MSG_ERROR([geos-config not executable.]) fi fi AC_MSG_CHECKING(geos-config usability) if test `${GEOS_CONFIG} --version` then GEOS_CLIBS="`${GEOS_CONFIG} --clibs`" #GEOS_DEP_CLIBS=`geos-config --static-clibs` -- this gives -m instead of -lm, which breaks clang # fixed in 3.7.0 at https://github.com/libgeos/libgeos/pull/73#issuecomment-262208677 GEOS_DEP_CLIBS=`${GEOS_CONFIG} --static-clibs | sed 's/-m/-lm/g'` GEOS_CPPFLAGS=`${GEOS_CONFIG} --cflags` AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) AC_MSG_ERROR([${GEOS_CONFIG} not usable]) fi GEOS_VERSION=`${GEOS_CONFIG} --version` AC_MSG_NOTICE([GEOS: ${GEOS_VERSION}]) AC_MSG_CHECKING([GEOS version >= 3.4.0]) # GDAL 2.0.1 requires GEOS 3.1.0 GEOS_VER_DOT=`echo $GEOS_VERSION | tr -d ".[[:alpha:]]"` if test ${GEOS_VER_DOT} -lt 340 ; then AC_MSG_RESULT(no) AC_MSG_ERROR([upgrade GEOS to 3.4.0 or later]) else AC_MSG_RESULT(yes) fi AC_SUBST([PKG_CPPFLAGS], ["${INPKG_CPPFLAGS} ${PROJ_CPPFLAGS} ${GDAL_CPPFLAGS} ${GEOS_CPPFLAGS}"]) AC_SUBST([PKG_LIBS], ["${INPKG_LIBS} ${GDAL_LIBS}"]) if test "${NEED_DEPS}" = yes; then AC_SUBST([PKG_LIBS], ["${PKG_LIBS} ${GDAL_DEP_LIBS}"]) fi # honor PKG_xx overrides # for CPPFLAGS we will superfluously double R's flags # since we'll set PKG_CPPFLAGS with this, but that shouldn't hurt CPPFLAGS="${CPPFLAGS} ${PKG_CPPFLAGS}" LIBS="${LIBS} ${PKG_LIBS}" geosok=yes AC_CHECK_HEADERS(geos_c.h,,geosok=no) if test "${geosok}" = no; then AC_MSG_ERROR([geos_c.h not found in given locations.]) fi [cat > geos_test.cpp <<_EOCONF #include #ifdef __cplusplus extern "C" { #endif static void __errorHandler(const char *fmt, ...) { return; } static void __warningHandler(const char *fmt, ...) { return; } int main() { GEOSContextHandle_t r = initGEOS_r((GEOSMessageHandler) __warningHandler, (GEOSMessageHandler) __errorHandler); finishGEOS_r(r); } #ifdef __cplusplus } #endif _EOCONF] #echo "${CXX} ${CPPFLAGS} -o geos_test geos_test.cpp ${LIBS}" AC_MSG_CHECKING(geos: linking with ${GEOS_CLIBS}) ${CXX} ${CPPFLAGS} -o geos_test geos_test.cpp ${GEOS_CLIBS} 2> errors.txt if test `echo $?` -ne 0 ; then geosok=no AC_MSG_RESULT(no) else AC_SUBST([PKG_LIBS], ["${PKG_LIBS} ${GEOS_CLIBS}"]) AC_MSG_RESULT(yes) fi if test "${geosok}" = no; then AC_MSG_CHECKING(geos: linking with ${GEOS_DEP_CLIBS}) ${CXX} ${CPPFLAGS} -o geos_test geos_test.cpp ${GEOS_DEP_CLIBS} 2> errors.txt if test `echo $?` -ne 0 ; then geosok=no AC_MSG_RESULT(no) cat errors.txt AC_MSG_NOTICE([Install failure: compilation and/or linkage problems.]) AC_MSG_ERROR([initGEOS_r not found in libgeos_c.]) else AC_SUBST([PKG_LIBS], ["${PKG_LIBS} ${GEOS_DEP_CLIBS}"]) AC_MSG_RESULT(yes) fi fi rm -f geos_test errors.txt geos_test.cpp # # add PROJ_LIBS # AC_SUBST([PKG_LIBS], ["${PROJ_LIBS} ${PKG_LIBS}"]) # # concluding substitution # AC_MSG_NOTICE([Package CPP flags: ${PKG_CPPFLAGS}]) AC_MSG_NOTICE([Package LIBS: ${PKG_LIBS}]) AC_CONFIG_FILES(src/Makevars) AC_OUTPUT