diff --git a/experiments/sweeps3.nim b/experiments/sweeps3.nim index 655783e..6d81fbd 100644 --- a/experiments/sweeps3.nim +++ b/experiments/sweeps3.nim @@ -64,6 +64,10 @@ var hourGlass = parsePath(""" M 20 20 L 180 20 L 20 180 L 180 180 z """) +var hourGlass2 = parsePath(""" + M 20 20 L 180 20 L 20 180 L 180 180 z M 62 24 L 132 24 L 50 173 L 156 173 z +""") + # Hole var hole = parsePath(""" M 40 40 L 40 160 L 160 160 L 160 40 z @@ -88,6 +92,8 @@ when defined(bench): test("cricle", cricle, 100) test("halfAarc", halfAarc, 100) test("hourGlass", hourGlass, 100) + test("hourGlass2", hourGlass2, wr=wrNonZero) + test("hourGlass2", hourGlass2, wr=wrEvenOdd) test("hole", hole, 100) test("holeEvenOdd", holeEvenOdd, 100, wr=wrNonZero) test("holeEvenOdd", holeEvenOdd, 100, wr=wrEvenOdd) @@ -99,7 +105,8 @@ else: # test("cricle", cricle) # test("halfAarc", halfAarc) # test("hourGlass", hourGlass) - #test("hole", hole, wr=wrEvenOdd) - test("holeEvenOdd", holeEvenOdd, wr=wrNonZero) - test("holeEvenOdd", holeEvenOdd, wr=wrEvenOdd) + test("hourGlass2", hourGlass2, wr=wrEvenOdd) + # test("hole", hole, wr=wrEvenOdd) + # test("holeEvenOdd", holeEvenOdd, wr=wrNonZero) + # test("holeEvenOdd", holeEvenOdd, wr=wrEvenOdd) # test("letterG", letterG) diff --git a/experiments/trapezoids/output_sweep.png b/experiments/trapezoids/output_sweep.png index 4835f2d..516a83a 100644 Binary files a/experiments/trapezoids/output_sweep.png and b/experiments/trapezoids/output_sweep.png differ diff --git a/src/pixie/fileformats/svg.nim b/src/pixie/fileformats/svg.nim index f786db8..293d3a2 100644 --- a/src/pixie/fileformats/svg.nim +++ b/src/pixie/fileformats/svg.nim @@ -2,6 +2,7 @@ import chroma, pixie/common, pixie/images, pixie/internal, pixie/paints, pixie/paths, strutils, tables, vmath, xmlparser, xmltree + when defined(pixieDebugSvg): import strtabs diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim index e219689..fe51b71 100644 --- a/src/pixie/paths.nim +++ b/src/pixie/paths.nim @@ -2267,78 +2267,46 @@ when defined(pixieSweeps): i = 0 while i < sweeps.len: # TODO: Maybe finds all cuts first, add them to array, cut all lines at once. - for t in 0 ..< 10: # TODO: maybe while true: - # keep cutting sweep - var needsCut = false - var cutterLine: float32 = 0 - block doubleFor: - for a in sweeps[i]: - let aSeg = segment( - vec2(a.atx, cutLines[i]), - vec2(a.tox, cutLines[i+1]) - ) - for b in sweeps[i]: - let bSeg = segment( - vec2(b.atx, cutLines[i]), - vec2(b.tox, cutLines[i+1]) - ) - var at: Vec2 - if intersectsInner(aSeg, bSeg, at): - needsCut = true - cutterLine = at.y - break doubleFor - # TODO enable? - if false and needsCut: - # Doing a cut. - var - thisSweep = sweeps[i] - sweeps[i].setLen(0) - sweeps.insert(newSeq[SweepLine](), i + 1) - for a in thisSweep: - let seg = segment(vec2(a.atx, cutLines[i]), vec2(a.tox, cutLines[i+1])) - var at: Vec2 - if intersects(line(vec2(0, cutterLine), vec2(1, cutterLine)), seg, at): - sweeps[i+0].add(toLine((segment(seg.at, at), a.winding))) - sweeps[i+1].add(toLine((segment(at, seg.to), a.winding))) - cutLines.binaryInsert(cutterLine) - else: - break - inc i + var crossCuts: seq[float32] - # i = 0 - # while i < sweeps.len: - # # TODO: Maybe finds all cuts first, add them to array, cut all lines at once. - # for t in 0 ..< 10: # TODO: maybe while true: - # # keep cutting sweep - # var needsCut = false - # var cutterLine: float32 = 0 - # block doubleFor: - # for a in sweeps[i]: - # let aSeg = segment(vec2(a.atx, cutLines[i]), vec2(a.tox, cutLines[i+1])) - # for b in sweeps[i]: - # let bSeg = segment(vec2(b.atx, cutLines[i]), vec2(b.tox, cutLines[i+1])) - # var at: Vec2 - # if intersectsInner(aSeg, bSeg, at): - # needsCut = true - # cutterLine = at.y - # break doubleFor - # # TODO enable? - # if false and needsCut: - # # Doing a cut. - # var - # thisSweep = sweeps[i] - # sweeps[i].setLen(0) - # sweeps.insert(newSeq[SweepLine](), i + 1) - # for a in thisSweep: - # let seg = segment(vec2(a.atx, cutLines[i]), vec2(a.tox, cutLines[i+1])) - # var at: Vec2 - # if intersects(line(vec2(0, cutterLine), vec2(1, cutterLine)), seg, at): - # sweeps[i+0].add(toLine((segment(seg.at, at), a.winding))) - # sweeps[i+1].add(toLine((segment(at, seg.to), a.winding))) - # cutLines.binaryInsert(cutterLine) - # else: - # break - # inc i + # echo i, " cut?" + + for aIndex in 0 ..< sweeps[i].len: + let a = sweeps[i][aIndex] + # echo i, ":", sweeps.len, ":", cutLines.len + let aSeg = segment(vec2(a.atx, cutLines[i]), vec2(a.tox, cutLines[i+1])) + for bIndex in aIndex + 1 ..< sweeps[i].len: + let b = sweeps[i][bIndex] + let bSeg = segment(vec2(b.atx, cutLines[i]), vec2(b.tox, cutLines[i+1])) + var at: Vec2 + if intersectsInner(aSeg, bSeg, at): + crossCuts.binaryInsert(at.y) + + if crossCuts.len > 0: + var + thisSweep = sweeps[i] + yTop = cutLines[i] + yBottom = cutLines[i + 1] + sweeps[i].setLen(0) + + for k in crossCuts: + let prevLen = cutLines.len + cutLines.binaryInsert(k) + if prevLen != cutLines.len: + sweeps.insert(newSeq[SweepLine](), i + 1) + + for a in thisSweep: + var seg = segment(vec2(a.atx, yTop), vec2(a.tox, yBottom)) + var at: Vec2 + for j, cutterLine in crossCuts: + if intersects(line(vec2(0, cutterLine), vec2(1, cutterLine)), seg, at): + sweeps[i+j].add(toLine((segment(seg.at, at), a.winding))) + seg = segment(at, seg.to) + sweeps[i+crossCuts.len].add(toLine((seg, a.winding))) + + i += crossCuts.len + + inc i i = 0 while i < sweeps.len: diff --git a/tests/benchmark_svg.nim b/tests/benchmark_svg.nim index c158d6d..b44ffc3 100644 --- a/tests/benchmark_svg.nim +++ b/tests/benchmark_svg.nim @@ -1,6 +1,9 @@ -import benchy, pixie/fileformats/svg +import benchy, pixie/fileformats/svg, pixie/fileformats/png let data = readFile("tests/fileformats/svg/Ghostscript_Tiger.svg") +#let data = readFile("tests/fileformats/svg/rotatedRect.svg") + +writeFile("tiger.png", decodeSvg(data).encodePng()) timeIt "svg decode": discard decodeSvg(data)