Skip to content

Filled vector contours

5 messages · Brian Ripley, Jan Tosovsky, David Winsemius

#
Dear All,

I am trying to create vector output (SVG) of filled contours. 

I've found two approaches so far:

(1)
library('lattice')
svg("D:/test.svg")
filled.contour(volcano)
#levelplot(volcano, panel=panel.levelplot.raster) # panel.levelplot.raster
will make it raster
dev.off()

(2)
library("raster")
svg("D:/test.svg")
rr <- raster(t(volcano))
rc <- cut(rr, breaks= 10)
pols <- rasterToPolygons(rc, dissolve=T)
spplot(pols)
dev.off()

But I'd like to get smooth closed polygons not broken into small cells.

Are there better methods in R ?

Thanks, Jan
#
On 24/08/2014 08:51, Jan Tosovsky wrote:
But the region between two contours is not in general a closed polygon.
Neither of those are 'in R'!

So you need to define your terms, precisely.  How can a polygon (with 
piecewise linear boundaries) be 'smooth'?

But you could get a long way by looking at the following

?contourLines
?polygon
?grid::grid.polygon

all of which are part of R.  R is a fully-fledged programming language 
and you could write SVG directly from R: using the svg device is limited 
by the steps to the R graphics primitives (see the 'R Internals' manual) 
and cairographics.

  
    
#
On 2014-08-24 Prof Brian Ripley wrote:
This was related to the result of example (2), which is more coarse
comparing it to the result of (1).
I appologize for not being precise here.

My goal is to get something like this:
http://drifted.in/other/contours/composition.svg

which is a composition of level plots, e.g.
http://drifted.in/other/contours/level_plot.svg

By 'level plot' I mean the cut of the data at certain level. It is always a
closed polygon (or multiple polygons) consisting of contour lines connected,
if required, by border lines. 

For me it is preferred way over 'isoband', which doesn't include areas
hidden by upper levels:
http://drifted.in/other/contours/isoband.svg

Please note I am not sure if this terminology (isoband, level plot, etc) is
correct.
Thanks a lot for detailed explanation. Now I understand it more.

Most of contouring libraries create the list of line fragments. And this
seems to be the case also of R's 'contourLines'.

But filling the areas requires a further post-processing (joining line
fragments, joining contours, set the correct direction to preserve holes).
And if I understand correctly, this is let to R 'libraries'. Unfortunately,
none of these two is optimal for my use case.

If there is any hidden option or another library (implementing e.g. Marching
squares) which could produce output similar to that linked SVG file, I am
one big ear.

Thanks, Jan
#
On Aug 24, 2014, at 1:30 PM, Jan Tosovsky wrote:

            
Most people with any R experience would have thought that "levelplot" referred to something like:
(Example 6.9 from Lattice, by Deepayan Sarkar to which I have only added the contour line parameter which it appears is what you were seeking.)

env <- environmental 
env$ozone <- env$ozone^(1/3) 
env$Radiation <- equal.count(env$radiation, 4)
fm1.env <- lm(ozone ~ radiation * temperature * wind, env) 
fm2.env <- loess(ozone ~ wind * temperature * radiation, env, span = 0.75, degree = 1) 
fm3.env <- loess(ozone ~ wind * temperature * radiation, env, parametric = c("radiation", "wind"), span = 0.75, degree = 2) 
library("locfit") ; library(lattice)
fm4.env <- locfit(ozone ~ wind * temperature * radiation, env) 
w.mesh <- with(env, do.breaks(range(wind), 50)) 
t.mesh <- with(env, do.breaks(range(temperature), 50)) 
r.mesh <- with(env, do.breaks(range(radiation), 3)) 
grid <- expand.grid(wind = w.mesh, temperature = t.mesh, radiation = r.mesh) 
grid[["fit.linear"]] <- predict(fm1.env, newdata = grid) 
grid[["fit.loess.1"]] <- as.vector(predict(fm2.env, newdata = grid)) 
grid[["fit.loess.2"]] <- as.vector(predict(fm3.env, newdata = grid)) 
grid[["fit.locfit"]] <- predict(fm4.env, newdata = grid)

png()
print(levelplot(fit.linear + fit.loess.1 + fit.loess.2 + fit.locfit ~ wind * temperature | radiation, data = grid, contour=TRUE))
dev.off()
#
On 2014-08-25 David Winsemius wrote:
Thanks, it looks similar, but in reality countours are just polylines not
connected into polygons and the fill is made from individual cells. But good
to know there is another way. I've realized it is a variant of commented
line in (1). So here is a simplified version:

(3)
library('lattice')
svg("D:/test.svg")
levelplot(volcano, contour=TRUE)
dev.off()

In the meantime I've found fourth one (based on Grid2Polygons library
example):

library(sp)
library(Grid2Polygons)
data(meuse.grid)
coordinates(meuse.grid) <- ~ x + y
gridded(meuse.grid) <- TRUE
meuse.grid <- as(meuse.grid, "SpatialGridDataFrame")
meuse.plys.lev <- Grid2Polygons(meuse.grid, "dist", level = TRUE)

svg("D:/meuse.svg")
plot(meuse.plys.lev, col = heat.colors(length(meuse.plys.lev)))
dev.off()

It is similar to (2). It actually doesn't produce smooth countours, just
joins cells into areas of the same fill/level. And these areas are
'isobands', not 'level plots' (or rather isolevels?).

I am leaving this open. For the future reference it would be nice to modify
code (4) for volcano data. I am lost here ;-)

Thanks, Jan