better with names

This commit is contained in:
Ryan Oldenburg 2021-05-29 15:57:55 -05:00
parent 85ae6ab3a9
commit f960349518

View file

@ -36,6 +36,10 @@ type
SomePath* = Path | string SomePath* = Path | string
Partitioning = object
partitions: seq[seq[(Segment, int16)]]
startY, partitionHeight: uint32
const const
epsilon = 0.0001 * PI ## Tiny value used for some computations. epsilon = 0.0001 * PI ## Tiny value used for some computations.
defaultMiterLimit*: float32 = 4 defaultMiterLimit*: float32 = 4
@ -1013,39 +1017,38 @@ proc computeBounds*(path: Path): Rect =
proc partitionSegments( proc partitionSegments(
segments: seq[(Segment, int16)], top, height: int segments: seq[(Segment, int16)], top, height: int
): (seq[seq[(Segment, int16)]], uint32, uint32) = ): Partitioning =
## Puts segments into the height partitions they intersect with. ## Puts segments into the height partitions they intersect with.
## Returns (partitions, startY, partitionHeight)
let let
maxPartitions = max(1, height div 10).uint32 maxPartitions = max(1, height div 10).uint32
numPartitions = min(maxPartitions, max(1, segments.len div 10).uint32) numPartitions = min(maxPartitions, max(1, segments.len div 10).uint32)
partitionHeight = height.uint32 div numPartitions
result[0].setLen(numPartitions) result.partitions.setLen(numPartitions)
result[1] = top.uint32 result.startY = top.uint32
result[2] = partitionHeight result.partitionHeight = height.uint32 div numPartitions
for (segment, winding) in segments: for (segment, winding) in segments:
if partitionHeight == 0: if result.partitionHeight == 0:
result[0][0].add((segment, winding)) result.partitions[0].add((segment, winding))
else: else:
var var
atPartition = max(0, segment.at.y - top.float32).uint32 atPartition = max(0, segment.at.y - result.startY.float32).uint32
toPartition = max(0, ceil(segment.to.y - top.float32)).uint32 toPartition = max(0, ceil(segment.to.y - result.startY.float32)).uint32
atPartition = atPartition div partitionHeight atPartition = atPartition div result.partitionHeight
toPartition = toPartition div partitionHeight toPartition = toPartition div result.partitionHeight
atPartition = clamp(atPartition, 0, result[0].high.uint32) atPartition = clamp(atPartition, 0, result.partitions.high.uint32)
toPartition = clamp(toPartition, 0, result[0].high.uint32) toPartition = clamp(toPartition, 0, result.partitions.high.uint32)
for i in atPartition .. toPartition: for i in atPartition .. toPartition:
result[0][i].add((segment, winding)) result.partitions[i].add((segment, winding))
proc getIndexForY( proc getIndexForY(partitioning: Partitioning, y: int): uint32 {.inline.} =
partitions: (seq[seq[(Segment, int16)]], uint32, uint32), y: int if partitioning.partitionHeight == 0 or partitioning.partitions.len == 1:
): uint32 {.inline.} =
if partitions[2] == 0 or partitions[0].len == 1:
0.uint32 0.uint32
else: else:
min((y.uint32 - partitions[1]) div partitions[2], partitions[0].high.uint32) min(
(y.uint32 - partitioning.startY) div partitioning.partitionHeight,
partitioning.partitions.high.uint32
)
proc quickSort(a: var seq[(float32, int16)], inl, inr: int) = proc quickSort(a: var seq[(float32, int16)], inl, inr: int) =
## Sorts in place + faster than standard lib sort. ## Sorts in place + faster than standard lib sort.
@ -1081,7 +1084,7 @@ template computeCoverages(
hits: var seq[(float32, int16)], hits: var seq[(float32, int16)],
size: Vec2, size: Vec2,
y: int, y: int,
partitions: (seq[seq[(Segment, int16)]], uint32, uint32), partitioning: Partitioning,
windingRule: WindingRule windingRule: WindingRule
) = ) =
const const
@ -1093,7 +1096,7 @@ template computeCoverages(
zeroMem(coverages[0].addr, coverages.len) zeroMem(coverages[0].addr, coverages.len)
# Do scanlines for this row # Do scanlines for this row
let partition = getIndexForY(partitions, y) let partition = getIndexForY(partitioning, y)
var var
yLine = y.float32 + initialOffset - offset yLine = y.float32 + initialOffset - offset
numHits: int numHits: int
@ -1101,7 +1104,7 @@ template computeCoverages(
yLine += offset yLine += offset
let scanline = line(vec2(0, yLine), vec2(size.x, yLine)) let scanline = line(vec2(0, yLine), vec2(size.x, yLine))
numHits = 0 numHits = 0
for (segment, winding) in partitions[0][partition]: for (segment, winding) in partitioning.partitions[partition]:
if segment.at.y <= scanline.a.y and segment.to.y >= scanline.a.y: if segment.at.y <= scanline.a.y and segment.to.y >= scanline.a.y:
var at: Vec2 var at: Vec2
if scanline.intersects(segment, at) and segment.to != at: if scanline.intersects(segment, at) and segment.to != at: