-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathREADME.Rmd
178 lines (123 loc) · 5.59 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
---
output: github_document
editor_options:
chunk_output_type: console
---
<!-- badges: start -->
[](https://github.com/hypertidy/laridae/actions)
<!-- badges: end -->
<!-- README.md is generated from README.Rmd. Please edit that file -->
```{r, echo = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%",
fig.width=12, fig.height=8
)
```
Work in progress to get constrained and conforming Delaunay triangulation for shapes in R with CGAL. We have
* point-only triangulation in `tri_xy()` - it's fast
* segment-input constraints in `insert_mesh()` - only returns the vertices, which might include new points
* constrained and conformal triangulations in-progress ...
We need:
* export of new vertex pool and its edge- or triangle-based indices
* proper inputs of nested polygon shapes
* robust dealing with segment and polygon soups, so that numeric insertions are robust (and c.)
We can now hit this more easily thanks to [cgal4h](https://CRAN.R-project.org/package=cgal4h) thanks
to Ahmadou Dicko.
`laridae` came out of a need for constrained triangulation for a topology-in-R project. That effort has moved on somewhat, proving the case by using `RTriangle` and then bedding down the normalization model in the `hypertidy/silicate` package.
R now has [cgal4h](https://cran.r-project.org/package=cgal4h) providing the library infrastructure for CGAL and [euclid](https:://github.com/thomasp85/euclid) providing numerically robust geometric primitives (it's unclear if laridae or whatever it becomes will use euclid).
RTriangle is really fast, but it's not as fast as CGAL. CGAL can also be used to update a triangulation, which means (I think) that we could build an unconstrained triangulation from all the coordinates, and then add in any segments, even unclosed linear paths. At any rate, being able to update a mesh has a lot of applications, especially for neighbouring shapes, and for on-demand (extent or zoom dependent level of detail) tasks.
The interest (which seems miniscule ...) in constrained triangulations is discussed here along with the overall landscape in R.
https://github.com/r-spatial/discuss/issues/6
## Installation
```R
remotes::install_github("hypertidy/laridae")
## not universe ready yet
#install.packages("laridae", repos = "https://hypertidy.r-universe.dev")
```
## Triangulation
Triangulate with CGAL via [laridae](https://github.com/hypertidy/laridae). The function `tri_xy` performs an exact Delaunay triangulation on all vertices, returning a triplet-index for each triangle (zero-based in CGAL).
The variants `tri_xy1()` and `tri_xy2()` work slightly differently illustrating CGAL usage in C++ (thanks to Mark Padgham). 'xy1' order is not trivial ... but we ignore that for now.
```{r triangle}
library(laridae)
x <- c(0, 0, 1)
y <- c(0, 1, 1)
plot(x, y, pch = "+")
(idx0 <- tri_xy(x, y))
(idx1 <- tri_xy1(x, y))
(idx2 <- tri_xy2(x, y))
polygon(cbind(x, y)[idx0, ])
x <- c(2.3,3.0,7.0,1.0,3.0,8.0)
y <- c(2.3,3.0,2.0,5.0,8.0,9.0)
idx <- tri_xy(x, y)
plot(x, y, pch = "+", cex = 1.5)
polygon(cbind(x, y)[rbind(matrix(idx, 3L), NA), ], lty = 3)
```
Some timings, to show we aren't wildly off-base and that CGAL wins for raw unconstrained Delaunay triangulation.
```{r}
set.seed(90)
x <- rnorm(1e3, sd = 4)
y <- rnorm(1e3, sd = 2)
library(laridae)
# plot a matrix xy as points
# and add the triangulation indexed
# by structural triplet row-identifiers
poly_index <- function(xy, index, ...) {
plot(xy, ...)
## assume index is 0,1,2,0,1,2,0,1,...
ii <- c(rbind(matrix(index, nrow = 3), NA_integer_))
## have forgetten why polypath fails, so just use polygon
polygon(xy[ii, 1], xy[ii, 2])
}
ps <- RTriangle::pslg(P = cbind(x, y))
microbenchmark::microbenchmark(
ind_t <- tri_xy(x, y),
ind_t1 <- tri_xy1(x, y),
ind_t2 <- tri_xy2(x, y),
RT <- RTriangle::triangulate(ps)
)
length(ind_t)
length(ind_t1)
length(ind_t2)
length(RT$T)
p <- par(mfrow = c(2, 2), mar = rep(0, 4))
poly_index(cbind(x, y), ind_t, pch = ".")
## can't work as order is not aligned, but still fun
poly_index(cbind(x, y), ind_t1, pch = ".")
poly_index(cbind(x, y), ind_t2, pch = ".")
plot(RT)
par(p)
```
## Constrained triangulation
Currently laridae only has vertex-output and "reporting" of the result. I can't yet see how to
* get the vertex pool (it may have expanded given mesh properties, overlapping segments, etc.)
* get the triangle index
The only other implementation in R is in RTriangle, so we use that for comparison.
```{r mesh-input, echo=TRUE}
sfx <- silicate::inlandwaters
sc <- silicate::SC(sfx)
X <- sc$vertex$x_
Y <- sc$vertex$y_
i0 <- match(sc$edge$.vx0, sc$vertex$vertex_)
i1 <- match(sc$edge$.vx1, sc$vertex$vertex_)
system.time(insert_constraint(X, Y, i0 , i1))
system.time(segment_constraint(sc))
## insert_mesh actually returns the vertices (which might include new ones)
system.time(xy_out <- insert_mesh(X, Y, i0 , i1))
plot(xy_out, pch = ".")
## compare RTriangle, it's fast if we don't include pslg() time
ps <- RTriangle::pslg(cbind(X, Y), S = cbind(i0, i1))
system.time({
tr <- RTriangle::triangulate(ps, D = TRUE)
})
plot(tr$P, pch= ".")
segments(tr$P[tr$E[,1],1], tr$P[tr$E[,1],2],
tr$P[tr$E[,2],1], tr$P[tr$E[,2],2])
str(tr)
```
## History
Was originally called `cgalgris`.
## Code of Conduct
Please note that the laridae project is released with a [Contributor Code of Conduct](https://contributor-covenant.org/version/1/0/0/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms.