Skip to content

Commit

Permalink
add <?xml> element to allow comments before <svg>; added test case fo…
Browse files Browse the repository at this point in the history
…r --colours
  • Loading branch information
StarsoftAnalysis committed Apr 9, 2024
1 parent 293bc8a commit 44b13f5
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 15 deletions.
15 changes: 9 additions & 6 deletions hc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ func TestContourFinder(t *testing.T) {
{3.998, 4.500}, {3.500, 4.002}, {2.998, 3.500}},
}, 3, 39.832},
{"tests/example.png", nil, 10, 3663.063},
{"tests/bottom.png", nil, 155, 6699.664},
}
for _, td := range testdata {
fmt.Printf("\t%s\n", td.infile)
Expand Down Expand Up @@ -296,19 +295,23 @@ func TestCreateSVG(t *testing.T) {
framewidth float64
paper string
clip bool
colours string
wanted string
}
testdata := []testdataT{ // Compression is done for SVG contours
{"tests/test3.png", "tests/test3-hc-t128m15pA4LF2.svg", []int{128}, 15, 2.0, "A4L", false,
"<svg width=\"297mm\" height=\"210mm\" viewBox=\"0 0 297 210\" style=\"background-color:white\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" encoding=\"UTF-8\" >\n<!-- tests/test3-hc-t128m15pA4LF2.svg, created by hcontours.test version 0.1.2 -->\n<g stroke=\"black\" stroke-width=\"0.0455\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\" transform=\"translate(60.5000,17.0000) scale(22.0000)\">\n<g inkscape:groupmode=\"layer\" inkscape:label=\"0 background\" stroke=\"black\" >\n<rect id=\"frame\" width=\"8.0909\" height=\"8.0909\" x=\"-0.0455\" y=\"-0.0455\" stroke-width=\"0.0909\" />\n</g>\n<g inkscape:groupmode=\"layer\" inkscape:label=\"128 contour\" stroke=\"black\" >\n<polyline id=\"0\" points=\"1.00,0.50 1.50,0.00 \" />\n<polyline id=\"1\" points=\"2.50,0.00 3.00,0.50 3.00,1.50 1.50,3.00 0.50,3.00 0.00,2.50 \" />\n<polyline id=\"2\" points=\"0.00,1.50 1.00,0.50 \" />\n<polyline id=\"3\" points=\"4.00,0.50 4.50,0.00 \" />\n<polyline id=\"4\" points=\"0.00,4.50 0.50,4.00 2.50,4.00 4.00,2.50 4.00,0.50 \" />\n<polygon id=\"0\" points=\"5.00,4.50 5.50,4.00 6.00,4.50 6.00,5.50 5.50,6.00 4.50,6.00 4.00,5.50 5.00,4.50 \" />\n</g>\n<!-- 3 contours found at threshold 128, with length 1.00m -->\n<!-- Total contour length: 1.00m -->\n</g>\n</svg>\n",
{"tests/test3.png", "tests/test3-hc-t128m15pA4LF2.svg", []int{128}, 15, 2.0, "A4L", false, "",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!-- tests/test3-hc-t128m15pA4LF2.svg, created by hcontours.test version 0.1.2 -->\n<!-- Options used: infile: \"tests/test3.png\", width: 8, height: 8, thresholds: [128], tcount: -1, margin: 15.00, paper: \"A4L\", paperSize: {297.00, 210.00}, image: false, clip: false, debug: false, linewidth: 1.00, framewidth: 2.00, colours: \"\" -->\n<svg width=\"297mm\" height=\"210mm\" viewBox=\"0 0 297 210\" style=\"background-color:white\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" encoding=\"UTF-8\" >\n<g stroke=\"black\" stroke-width=\"0.0455\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\" transform=\"translate(60.5000,17.0000) scale(22.0000)\">\n<g inkscape:groupmode=\"layer\" inkscape:label=\"0 background\" stroke=\"black\" >\n<rect id=\"frame\" width=\"8.0909\" height=\"8.0909\" x=\"-0.0455\" y=\"-0.0455\" stroke-width=\"0.0909\" />\n</g>\n<g inkscape:groupmode=\"layer\" inkscape:label=\"128 contour\" stroke=\"black\" >\n<polyline id=\"0\" points=\"1.00,0.50 1.50,0.00 \" />\n<polyline id=\"1\" points=\"2.50,0.00 3.00,0.50 3.00,1.50 1.50,3.00 0.50,3.00 0.00,2.50 \" />\n<polyline id=\"2\" points=\"0.00,1.50 1.00,0.50 \" />\n<polyline id=\"3\" points=\"4.00,0.50 4.50,0.00 \" />\n<polyline id=\"4\" points=\"0.00,4.50 0.50,4.00 2.50,4.00 4.00,2.50 4.00,0.50 \" />\n<polygon id=\"0\" points=\"5.00,4.50 5.50,4.00 6.00,4.50 6.00,5.50 5.50,6.00 4.50,6.00 4.00,5.50 5.00,4.50 \" />\n</g>\n<!-- 3 contours found at threshold 128, with length 1.00m -->\n<!-- Total contour length: 1.00m -->\n</g>\n</svg>\n",
},
{"tests/test4.png", "tests/test4-hc-t100,200m15pA4PC.svg", []int{100, 200}, 15, 0.0, "A4P", true,
"<svg width=\"210mm\" height=\"297mm\" viewBox=\"0 0 210 297\" style=\"background-color:white\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" encoding=\"UTF-8\" >\n<!-- tests/test4-hc-t100,200m15pA4PC.svg, created by hcontours.test version 0.1.2 -->\n<g stroke=\"black\" stroke-width=\"0.0333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\" transform=\"translate(15.0000,88.5000) scale(30.0000)\">\n<defs><clipPath id=\"clip1\" ><rect id=\"cliprect\" width=\"5.9667\" height=\"3.9667\" x=\"0.0167\" y=\"0.0167\" /></clipPath></defs>\n<g inkscape:groupmode=\"layer\" inkscape:label=\"0 background\" stroke=\"black\" >\n</g>\n<g inkscape:groupmode=\"layer\" inkscape:label=\"200 contour\" stroke=\"black\" >\n<path id=\"0\" clip-path=\"url(#clip1)\" d=\"M 0.72,0.50 L 1.50,-0.00 L 2.28,0.50 L 3.28,1.50 L 3.28,2.50 L 2.28,3.50 L 1.50,4.00 L 0.72,3.50 L 0.50,3.28 L -0.00,2.50 L -0.00,1.50 L 0.50,0.72 L 0.72,0.50 Z M 3.72,0.50 L 4.50,-0.00 L 5.50,-0.00 L 6.00,0.50 L 6.00,1.50 L 5.50,2.28 L 4.50,2.28 L 3.72,1.50 L 3.72,0.50 Z M 3.72,3.50 L 4.50,2.72 L 5.28,3.50 L 4.50,4.00 L 3.72,3.50 Z \" />\n</g>\n<g inkscape:groupmode=\"layer\" inkscape:label=\"100 contour\" stroke=\"black\" >\n<path id=\"1\" clip-path=\"url(#clip1)\" d=\"M 1.11,0.50 L 1.50,-0.00 L 1.89,0.50 L 2.89,1.50 L 2.89,2.50 L 1.89,3.50 L 1.50,4.00 L 1.11,3.50 L 0.50,2.89 L -0.00,2.50 L -0.00,1.50 L 0.50,1.11 L 1.11,0.50 Z M 4.11,0.50 L 4.50,-0.00 L 5.50,-0.00 L 6.00,0.50 L 6.00,1.50 L 5.50,1.89 L 4.50,1.89 L 4.11,1.50 L 4.11,0.50 Z M 4.11,3.50 L 4.50,3.11 L 4.89,3.50 L 4.50,4.00 L 4.11,3.50 Z \" />\n</g>\n<!-- 3 contours found at threshold 100, with length 0.58m -->\n<!-- 3 contours found at threshold 200, with length 0.68m -->\n<!-- Total contour length: 1.26m -->\n</g>\n</svg>\n",
{"tests/test4.png", "tests/test4-hc-t100,200m15pA4PC.svg", []int{100, 200}, 15, 0.0, "A4P", true, "",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!-- tests/test4-hc-t100,200m15pA4PC.svg, created by hcontours.test version 0.1.2 -->\n<!-- Options used: infile: \"tests/test4.png\", width: 6, height: 4, thresholds: [100 200], tcount: -1, margin: 15.00, paper: \"A4P\", paperSize: {210.00, 297.00}, image: false, clip: true, debug: false, linewidth: 1.00, framewidth: 0.00, colours: \"\" -->\n<svg width=\"210mm\" height=\"297mm\" viewBox=\"0 0 210 297\" style=\"background-color:white\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" encoding=\"UTF-8\" >\n<g stroke=\"black\" stroke-width=\"0.0333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\" transform=\"translate(15.0000,88.5000) scale(30.0000)\">\n<defs><clipPath id=\"clip1\" ><rect id=\"cliprect\" width=\"5.9667\" height=\"3.9667\" x=\"0.0167\" y=\"0.0167\" /></clipPath></defs>\n<g inkscape:groupmode=\"layer\" inkscape:label=\"0 background\" stroke=\"black\" >\n</g>\n<g inkscape:groupmode=\"layer\" inkscape:label=\"200 contour\" stroke=\"black\" >\n<path id=\"0\" clip-path=\"url(#clip1)\" d=\"M 0.72,0.50 L 1.50,-0.00 L 2.28,0.50 L 3.28,1.50 L 3.28,2.50 L 2.28,3.50 L 1.50,4.00 L 0.72,3.50 L 0.50,3.28 L -0.00,2.50 L -0.00,1.50 L 0.50,0.72 L 0.72,0.50 Z M 3.72,0.50 L 4.50,-0.00 L 5.50,-0.00 L 6.00,0.50 L 6.00,1.50 L 5.50,2.28 L 4.50,2.28 L 3.72,1.50 L 3.72,0.50 Z M 3.72,3.50 L 4.50,2.72 L 5.28,3.50 L 4.50,4.00 L 3.72,3.50 Z \" />\n</g>\n<g inkscape:groupmode=\"layer\" inkscape:label=\"100 contour\" stroke=\"black\" >\n<path id=\"1\" clip-path=\"url(#clip1)\" d=\"M 1.11,0.50 L 1.50,-0.00 L 1.89,0.50 L 2.89,1.50 L 2.89,2.50 L 1.89,3.50 L 1.50,4.00 L 1.11,3.50 L 0.50,2.89 L -0.00,2.50 L -0.00,1.50 L 0.50,1.11 L 1.11,0.50 Z M 4.11,0.50 L 4.50,-0.00 L 5.50,-0.00 L 6.00,0.50 L 6.00,1.50 L 5.50,1.89 L 4.50,1.89 L 4.11,1.50 L 4.11,0.50 Z M 4.11,3.50 L 4.50,3.11 L 4.89,3.50 L 4.50,4.00 L 4.11,3.50 Z \" />\n</g>\n<!-- 3 contours found at threshold 100, with length 0.58m -->\n<!-- 3 contours found at threshold 200, with length 0.68m -->\n<!-- Total contour length: 1.26m -->\n</g>\n</svg>\n",
},
{"tests/test7.png", "tests/test7-hc-t85,171m15pA4LCff7700-0077ff.svg", []int{85, 171}, 15, 0.0, "A4L", true, "ff7700-0077ff",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!-- tests/test7-hc-t85,171m15pA4LCff7700-0077ff.svg, created by hcontours.test version 0.1.2 -->\n<!-- Options used: infile: \"tests/test7.png\", width: 5, height: 7, thresholds: [85 171], tcount: -1, margin: 15.00, paper: \"A4L\", paperSize: {297.00, 210.00}, image: false, clip: true, debug: false, linewidth: 1.00, framewidth: 0.00, colours: \"ff7700-0077ff\" -->\n<svg width=\"297mm\" height=\"210mm\" viewBox=\"0 0 297 210\" style=\"background-color:white\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" encoding=\"UTF-8\" >\n<g stroke=\"black\" stroke-width=\"0.0389\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\" transform=\"translate(84.2143,15.0000) scale(25.7143)\">\n<defs><clipPath id=\"clip1\" ><rect id=\"cliprect\" width=\"4.9611\" height=\"6.9611\" x=\"0.0194\" y=\"0.0194\" /></clipPath></defs>\n<g inkscape:groupmode=\"layer\" inkscape:label=\"0 background\" stroke=\"black\" fill=\"#0077ff\" >\n<rect id=\"plotsize\" width=\"5\" height=\"7\" stroke=\"none\" />\n</g>\n<g inkscape:groupmode=\"layer\" inkscape:label=\"171 contour\" stroke=\"black\" fill=\"#7f7780\" >\n<path id=\"0\" clip-path=\"url(#clip1)\" d=\"M 0.83,1.50 L 1.50,0.83 L 3.50,0.83 L 4.17,1.50 L 4.17,3.50 L 3.50,4.17 L 2.50,4.17 L 2.17,4.50 L 2.50,4.83 L 3.50,4.83 L 4.17,5.50 L 3.50,6.17 L 1.50,6.17 L 0.83,5.50 L 0.83,3.50 L 1.50,2.83 L 2.50,2.83 L 2.83,2.50 L 2.50,2.17 L 1.50,2.17 L 0.83,1.50 Z \" />\n</g>\n<g inkscape:groupmode=\"layer\" inkscape:label=\"85 contour\" stroke=\"black\" fill=\"#ff7700\" >\n<path id=\"1\" clip-path=\"url(#clip1)\" d=\"M 1.17,1.50 L 1.50,1.17 L 3.50,1.17 L 3.83,1.50 L 3.83,3.50 L 3.50,3.83 L 2.50,3.83 L 1.83,4.50 L 2.50,5.17 L 3.50,5.17 L 3.83,5.50 L 3.50,5.83 L 1.50,5.83 L 1.17,5.50 L 1.17,3.50 L 1.50,3.17 L 2.50,3.17 L 3.17,2.50 L 2.50,1.83 L 1.50,1.83 L 1.17,1.50 Z \" />\n</g>\n<!-- 1 contours found at threshold 85, with length 0.50m -->\n<!-- 1 contours found at threshold 171, with length 0.55m -->\n<!-- Total contour length: 1.05m -->\n</g>\n</svg>\n",
},
}
for _, td := range testdata {
fmt.Printf("\t%s\n", td.infile)
opts := OptsT{infile: td.infile, thresholds: td.thresholds, tcount: -1, margin: td.margin, framewidth: td.framewidth, paper: td.paper, clip: td.clip, linewidth: 1}
opts := OptsT{infile: td.infile, thresholds: td.thresholds, tcount: -1, margin: td.margin, framewidth: td.framewidth, paper: td.paper, clip: td.clip, linewidth: 1, colours: td.colours}
parsePaperSize(&opts)
svgFilename := createSVG(opts)
if svgFilename != td.outfile {
Expand Down
10 changes: 7 additions & 3 deletions hcontours.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,6 @@ func contourFinder(imageData *image.NRGBA, width, height int, threshold int, cli
svgF.closedPathStop()
}
// contours are really only returned for test cases
// FIXME some contours may not have generated an SVG e.g. heightmap1
// could return a value from plotContour
return contours, totalLen
}

Expand Down Expand Up @@ -342,7 +340,13 @@ func createSVG(opts OptsT) string {
opts.width = width
opts.height = height
svgFilename := buildSVGfilename(opts)
scale := svgF.openStart(svgFilename, opts)
svgF.open(svgFilename)
svgF.writeComment(fmt.Sprintf("%s, created by %s version %s", svgFilename, hcName, hcVersion))
// This doesn't work, because "--" in option prefixes messes with XML comments:
//svgF.writeComment(fmt.Sprintf("Command line: %s %s", path.Base(os.Args[0]), strings.Join(os.Args[1:], " ")))
// - could do something clever by extracing the command line information from spflag with short -x flags.
svgF.writeComment(fmt.Sprintf("Options used: %v", opts))
scale := svgF.start(opts)
contourText := make([]string, len(opts.thresholds))
totalLen := 0.0
for i := len(opts.thresholds) - 1; i >= 0; i-- {
Expand Down
14 changes: 8 additions & 6 deletions svg.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,16 +297,20 @@ func (svg *SVGfile) setColours(colourString string) {
//fmt.Printf("setColours: %#v\n", svg.colours)
}

func (svg *SVGfile) openStart(filename string, opts OptsT) (scale float64) {
func (svg *SVGfile) open(filename string) {
svg.filename = filename
svg.currentLayer = -1 // no layer open
svg.thresholds = append([]int{0}, opts.thresholds...) // the background counts as threshold 0
svg.setColours(opts.colours)
fh, err := os.Create(svg.filename)
if err != nil {
log.Fatalf("Unable to open SVG file %q - %s", svg.filename, err)
}
svg.file = fh
svg.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") // needed so that next line can be a comment
}

func (svg *SVGfile) start(opts OptsT) (scale float64) {
svg.currentLayer = -1 // no layer open
svg.thresholds = append([]int{0}, opts.thresholds...) // the background counts as threshold 0
svg.setColours(opts.colours)
// write the wrapper SVG with background colour first
viewbox := fmt.Sprintf("viewBox=\"0 0 %g %g\"", opts.paperSize.width, opts.paperSize.height)
// Set background via style rather than filling an oversized rect (which upsets Axidraw)
Expand All @@ -317,8 +321,6 @@ func (svg *SVGfile) openStart(filename string, opts OptsT) (scale float64) {
opts.paperSize.width, opts.paperSize.height, viewbox, bg, xmlns)
svg.write(svgElement)

svg.writeComment(fmt.Sprintf("%s, created by %s version %s", filename, hcName, hcVersion))

// Debug only: show paper limits
if opts.debug {
paperBox := fmt.Sprintf("<rect id=\"papersize\" width=\"%g\" height=\"%g\" stroke=\"blue\" stroke-dasharray=\"4\" fill=\"none\"/>\n", opts.paperSize.width, opts.paperSize.height)
Expand Down
Binary file removed tests/bottom.png
Binary file not shown.
4 changes: 4 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,5 +186,9 @@ type OptsT struct {
colours string // two hex colours, e.g. "0033ff,0c4088"
}

func (o OptsT) String() string {
return fmt.Sprintf("infile: \"%s\", width: %d, height: %d, thresholds: %v, tcount: %d, margin: %.2f, paper: \"%s\", paperSize: {%.2f, %.2f}, image: %t, clip: %t, debug: %t, linewidth: %.2f, framewidth: %.2f, colours: \"%s\"", o.infile, o.width, o.height, o.thresholds, o.tcount, o.margin, o.paper, o.paperSize.width, o.paperSize.height, o.image, o.clip, o.debug, o.linewidth, o.framewidth, o.colours)
}

const white = 0xff
const black = 0x00

0 comments on commit 44b13f5

Please sign in to comment.