go-nexrad
go-nexrad copied to clipboard
WASM Webapp and initial support for SVG rendering
WEBAPP
I have made a super rudimentary version of this project using wasm
, and it was taken almost entirely from go-wasm-pdfcpu.
To build the nexrad.wasm
file yourself, run
git clone https://github.com/bwiggs/go-nexrad.git
cd go-nexrad && cd cmd && cd nexrad-render
GOOS=js GOARCH=wasm go build -o nexrad.wasm
I struggled a while on Go 1.18 because I was getting some errors, but then I downgraded to 1.12 and it worked fine. Specifically go version go1.12 darwin/amd64
.
Then put the binary under the webapp directory I have made:
git clone https://github.com/SteepAtticStairs/go-nexrad.git
cd go-nexrad && cd webapp
These instructions are just if you want to build it yourself. A live demo of what I (but mostly the author of go-wasm-pdfcpu) have done can be found here: https://steepatticstairs.github.io/go-nexrad/webapp/
I plan to do a lot more cleanup.
VECTOR RENDERING
This is very scuffed code, forgive me - I mainly work with JavaScript, not Go! But this is a basic implementation of vector rendering using the draw2d
library. By passing the -v
flag with arguments png
or svg
(png is default), it will generate the relevant file.
However, I think there are three major issues with the code I have written. First, the file size of these svg files are extremely large, hovering around 70 MB. I have tried to reduce the DPI, the canvas size, but nothing has worked, so I would like to try and work out a solution in the future. Any suggestions on combatting this issue would be welcome.
Second issue (fixed for now I think??)
Second, the svg image has a slight problem with rendering the pixels closest to the origin. For example, when I generate an svg file from KLZK20220607_194517_V06
by doing go run . -f testdata/KLZK20220607_194517_V06 -p ref -v svg
, I get this error right in the middle of the image:
As you can see, there is a ring of thick pixels that shouldn't be there.
This is NOT an issue with PNG rendering.
Third, the variables canvas
and gc
have been replaced with PNGcanvas
PNGgc
and SVGcanvas
SVGgc
, and I will explain that here. I wanted to use an if
statement, basically giving these variables their proper arguments if the user passed png
or svg
. For example, the correct canvas
variable for an svg
render would be
canvas := draw2dsvg.NewSvg()
while the correct variable for a png
render would be
canvas := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
I wanted to set these dynamically with an if
statement, ideally something like this:
if vectorize == "png" {
canvas := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
draw.Draw(canvas, canvas.Bounds(), image.Black, image.ZP, draw.Src)
gc := draw2dimg.NewGraphicContext(canvas)
} else if vectorize == "svg" {
canvas := draw2dsvg.NewSvg()
canvas.Width = strconv.Itoa(int(width)) + "px"
canvas.Height = strconv.Itoa(int(width)) + "px"
gc := draw2dsvg.NewGraphicContext(canvas)
}
However, the issue with this is that each of these variables using :=
, which obviously means that they are declared and set in the same line, where they don't require you to specify a type. This will not work here, because you need to define the variables outside of the if
statement. You could do this by writing something like
var canvas *image.RGBA;
var gc *draw2dimg.GraphicContext;
if vectorize == "png" {
canvas = image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
draw.Draw(canvas, canvas.Bounds(), image.Black, image.ZP, draw.Src)
gc = draw2dimg.NewGraphicContext(canvas)
}
but this would mean you would have to change the types of canvas
and gc
for the case that the user renders an svg
.
My solution to this, of course, was to create two separate draw2d
objects that the program will draw to simultaneously, but only one will get exported to a file 😂. This, of course, is not the best way to do it, because it slows down the program and it looks quite ugly. Again, any suggestions on combatting this issue would be welcome.
Andrew
June 10, 2022 10:30 PM EST
See the original PR comment for more specific details. This comment is meant to provide an easy way to look at my changes, so you don't only have to go digging through my super messy and unnecessarily plentiful commits.
TOTAL COMMITS SO FAR: 15 🤦♂️
Summary of PR so far:
- I have made some changes to the code, mostly in
cmd/nexrad-render/main.go
- added a timer that prints out how long the rendering of the radar file took
- commented out the pb library, because it wasn't allowing WASM to compile and it wasn't serving much purpose in the first place (that I could tell)
- updated a couple of
gitignore
s to make working with my input and output files easier
- Added two new command flags for
svg
vector rendering, detailed below -
-v svg
- generates an SVG image using the
draw2d
library, exactly how apng
image is created, but withsvg
options. Highly inefficient, most outputsvg
s are over 70 MB. - default output name is
radar.svg
- generates an SVG image using the
-
-v svgtest
- Uses another library for svg generation: svgo. Draws each radial gate as a single circle, in an attempt to make it more efficient. Uglier output, but 40 MB compared to 95 MB of the same radar file generated using the method above.
- default output name is
TESTradar.svg
- added a new folder under
cmd/nexrad-render
calleddump
. Contains a file calledsvgMinify.go
, using the library minify for svg minimization. works ok-ish, 95 MB svg becomes around 70 MB. not the best, and it will not compile into WASM, so I kept the code but moved it into a separate folder so it wouldn't get in the way. - added a web app under the directory
webapp
, live demo here- allows you to upload a radar file, specify command flags, and it will give you the resulting png/svg output.
- I also wrote a small utility on that page for browsing the AWS S3 bucket of L2 radar files, which provides quick downloads for the files. Specify a date and a radar station and it will list all radar files stored for that date as anchor elements, which link to the file URL - which you can click on and download.
- This radar download utility might take a bit to load the file list, because it has to use a proxy to bypass a CORS error.
Sorry about this getting closed. I've update the repo to use main
as the new default branch.
June 14, 2022 11:15 PM EST
See the original PR comment for more specific details. This comment is meant to provide an easy way to look at my changes, so you don't only have to go digging through my super messy and unnecessarily plentiful commits.
TOTAL COMMITS SO FAR: 34 🤦♂️
Summary of PR so far (things that have changed / been added since the last summary comment):
-
-v svg
and-v svgtest
- These flags now generate a new directory in
cmd/nexrad-render
calledradials
. inside theradials/split
directory there are around 70 svg files, each file containing 10 radials. This is toying with the idea I had where I assumed that if I wanted to render the radar image onto a map, it would be easier for the map to render a lot of smaller images at once than one big image. - Transparent gates are no longer rendered at all, cutting a
95 MB
file down to around60 MB
. - The main output svg for
-v svg
is now gzipped intoradar.svg.gz
, for further compression. Plans to gzip theradials
directory as well.
- These flags now generate a new directory in
-
-v png
- Background is now transparent instead of black
- Leaflet map
- I have added a leaflet map page to
webapp/map.html
, and a demo can be found here. - First, upload a radar file generated from
go-nexrad
. Then, input a radar station and hitOk
. Finally, press the picture frame button on the left hand side of the map to show and hide the image. - Gets the coordinates of each radar station from a master
JSON
I have here. Calculates a bounding box by getting a point460 km
to the northwest and460 km
to the southeast. Loads the uploaded image into that bounding box. - The image is slightly misaligned, only by a little bit. This is a bug, but I am not sure what is causing it. The circle in the middle of the radar image should be centered on the coordinates of the radar station, but the image is always a little off.
- I have added a leaflet map page to