| 147 | } |
| 148 | |
| 149 | func (r *RotatedRectangle) Rasterize() []Scanline { |
| 150 | w := r.Worker.W |
| 151 | h := r.Worker.H |
| 152 | sx, sy := float64(r.Sx), float64(r.Sy) |
| 153 | angle := radians(float64(r.Angle)) |
| 154 | rx1, ry1 := rotate(-sx/2, -sy/2, angle) |
| 155 | rx2, ry2 := rotate(sx/2, -sy/2, angle) |
| 156 | rx3, ry3 := rotate(sx/2, sy/2, angle) |
| 157 | rx4, ry4 := rotate(-sx/2, sy/2, angle) |
| 158 | x1, y1 := int(rx1)+r.X, int(ry1)+r.Y |
| 159 | x2, y2 := int(rx2)+r.X, int(ry2)+r.Y |
| 160 | x3, y3 := int(rx3)+r.X, int(ry3)+r.Y |
| 161 | x4, y4 := int(rx4)+r.X, int(ry4)+r.Y |
| 162 | miny := minInt(y1, minInt(y2, minInt(y3, y4))) |
| 163 | maxy := maxInt(y1, maxInt(y2, maxInt(y3, y4))) |
| 164 | n := maxy - miny + 1 |
| 165 | min := make([]int, n) |
| 166 | max := make([]int, n) |
| 167 | for i := range min { |
| 168 | min[i] = w |
| 169 | } |
| 170 | xs := []int{x1, x2, x3, x4, x1} |
| 171 | ys := []int{y1, y2, y3, y4, y1} |
| 172 | // TODO: this could be better probably |
| 173 | for i := 0; i < 4; i++ { |
| 174 | x, y := float64(xs[i]), float64(ys[i]) |
| 175 | dx, dy := float64(xs[i+1]-xs[i]), float64(ys[i+1]-ys[i]) |
| 176 | count := int(math.Sqrt(dx*dx+dy*dy)) * 2 |
| 177 | for j := 0; j < count; j++ { |
| 178 | t := float64(j) / float64(count-1) |
| 179 | xi := int(x + dx*t) |
| 180 | yi := int(y+dy*t) - miny |
| 181 | min[yi] = minInt(min[yi], xi) |
| 182 | max[yi] = maxInt(max[yi], xi) |
| 183 | } |
| 184 | } |
| 185 | lines := r.Worker.Lines[:0] |
| 186 | for i := 0; i < n; i++ { |
| 187 | y := miny + i |
| 188 | if y < 0 || y >= h { |
| 189 | continue |
| 190 | } |
| 191 | a := maxInt(min[i], 0) |
| 192 | b := minInt(max[i], w-1) |
| 193 | if b >= a { |
| 194 | lines = append(lines, Scanline{y, a, b, 0xffff}) |
| 195 | } |
| 196 | } |
| 197 | return lines |
| 198 | } |