-
Notifications
You must be signed in to change notification settings - Fork 108
Description
I have been using this library with go-nexrad, and I am able to generate PNG and SVG files. However, the SVG files that are generated are enormous, with a less than 10MB PNG file becoming a 28MB SVG file with the same options. Here is the code:
func render(out string, radials []*archive2.Message31, label string) {
width := float64(imageSize)
height := float64(imageSize)
SVGcanvas := draw2dsvg.NewSvg()
SVGcanvas.Width = strconv.Itoa(int(width)) + "px"
SVGcanvas.Height = strconv.Itoa(int(width)) + "px"
//fmt.Println(canvas.Width)
//fmt.Println(canvas.Height)
//draw.Draw(canvas, canvas.Bounds(), image.Black, image.ZP, draw.Src)
SVGgc := draw2dsvg.NewGraphicContext(SVGcanvas)
xc := width / 2
yc := height / 2
pxPerKm := width / 2 / 460
firstGatePx := float64(radials[0].ReflectivityData.DataMomentRange) / 1000 * pxPerKm
gateIntervalKm := float64(radials[0].ReflectivityData.DataMomentRangeSampleInterval) / 1000
gateWidthPx := gateIntervalKm * pxPerKm
t := time.Now()
log.Println("rendering radials")
// valueDist := map[float32]int{}
for _, radial := range radials {
// round to the nearest rounded azimuth for the given resolution.
// ex: for radial 20.5432, round to 20.5
azimuthAngle := float64(radial.Header.AzimuthAngle) - 90
if azimuthAngle < 0 {
azimuthAngle = 360.0 + azimuthAngle
}
azimuthSpacing := radial.Header.AzimuthResolutionSpacing()
azimuth := math.Floor(azimuthAngle)
if math.Floor(azimuthAngle+azimuthSpacing) > azimuth {
azimuth += azimuthSpacing
}
startAngle := azimuth * (math.Pi / 180.0) /* angles are specified */
endAngle := azimuthSpacing * (math.Pi / 180.0) /* clockwise in radians */
// start drawing gates from the start of the first gate
distanceX, distanceY := firstGatePx, firstGatePx
SVGgc.SetLineWidth(gateWidthPx + 1)
SVGgc.SetLineCap(draw2d.ButtCap)
var gates []float32
switch product {
case "vel":
gates = radial.VelocityData.ScaledData()
case "sw":
gates = radial.SwData.ScaledData()
case "rho":
gates = radial.RhoData.ScaledData()
default:
gates = radial.ReflectivityData.ScaledData()
}
numGates := len(gates)
for i, v := range gates {
if v != archive2.MomentDataBelowThreshold {
//fmt.Println(gateWidthPx)
if i == 0 {
SVGgc.SetLineWidth(0)
} else if i > 0 {
SVGgc.SetLineWidth(gateWidthPx + 1)
}
// valueDist[v] += 1
SVGgc.MoveTo(xc+math.Cos(startAngle)*distanceX, yc+math.Sin(startAngle)*distanceY)
// make the gates connect visually by extending arcs so there is no space between adjacent gates.
if i == 0 {
SVGgc.ArcTo(xc, yc, distanceX, distanceY, startAngle-.001, endAngle+.001)
} else if i == numGates-1 {
SVGgc.ArcTo(xc, yc, distanceX, distanceY, startAngle, endAngle)
} else {
SVGgc.ArcTo(xc, yc, distanceX, distanceY, startAngle, endAngle+.001)
}
SVGgc.SetStrokeColor(colorSchemes[product][colorScheme](v))
SVGgc.Stroke()
}
distanceX += gateWidthPx
distanceY += gateWidthPx
azimuth += radial.Header.AzimuthResolutionSpacing()
}
}
// Save to file
draw2dsvg.SaveToSvgFile(out, SVGcanvas)
fmt.Println("Finished in", time.Since(t))
}The full file can be found in my fork of the project here.
The reason I think the SVG is so large is because it is generating the file very inefficiently, possibly by trying to render every pixel instead of just a start and end point. I have tried setting the DPI with SVGgc.setDPI(), but that hasn't worked.
If you have any idea about why the file is so large, or any idea of how to fix it, I would greatly appreciate your input. Hopefully you won't have to go through the entire go-nexrad project to understand this, I have included the code block that I am almost certain is causing the issue, and is the part that uses your library.
If you would like a screen recording of me generating the file and showing the file size with both PNG and SVG, please let me know, if you have difficulty building the project and replicating the issue yourself, if that is needed.