Error detection in bresenham circle
109
main.py
@@ -7,66 +7,83 @@ from world_maker.data_analysis import transpose_form_heightmap
|
||||
from world_maker.Skeleton import Skeleton, simplify_coordinates
|
||||
from world_maker.terraforming import remove_trees, smooth_terrain
|
||||
from networks.geometry.Point3D import Point3D
|
||||
from networks.geometry.Point2D import Point2D
|
||||
from networks.roads_2.Road import Road
|
||||
from networks.legacy_roads import roads
|
||||
from world_maker.District import Road as Road_grid
|
||||
from networks.geometry.Circle import Circle
|
||||
from House import *
|
||||
from gdpc import Editor, Block
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
rectangle_house_mountain, rectangle_building, skeleton_highway, skeleton_mountain, road_grid = world_maker()
|
||||
|
||||
editor = Editor(buffering=True)
|
||||
buildArea = editor.getBuildArea()
|
||||
origin = ((buildArea.begin).x, (buildArea.begin).z)
|
||||
c = Circle(Point2D(400, -75)).circle_thick_by_line(5, 32)
|
||||
for i in range(len(c[0])):
|
||||
for j in range(len(c[0][i])):
|
||||
if i % 2 == 0:
|
||||
editor.placeBlock(
|
||||
(c[0][i][j].x, 110, c[0][i][j].y), Block("white_concrete"))
|
||||
else:
|
||||
editor.placeBlock(
|
||||
(c[0][i][j].x, 110, c[0][i][j].y), Block("black_concrete"))
|
||||
print(c[1])
|
||||
for i in range(len(c[1])):
|
||||
for j in range(len(c[1][i])):
|
||||
editor.placeBlock(
|
||||
(c[1][i][j].x, 110, c[1][i][j].y), Block("red_concrete"))
|
||||
# rectangle_house_mountain, rectangle_building, skeleton_highway, skeleton_mountain, road_grid = world_maker()
|
||||
|
||||
remove_trees('./world_maker/data/heightmap.png', './world_maker/data/treemap.png',
|
||||
'./world_maker/data/smooth_sobel_watermap.png')
|
||||
smooth_terrain('./world_maker/data/heightmap.png',
|
||||
'./world_maker/data/heightmap_smooth.png', './world_maker/data/smooth_sobel_watermap.png')
|
||||
# editor = Editor(buffering=True)
|
||||
# buildArea = editor.getBuildArea()
|
||||
# origin = ((buildArea.begin).x, (buildArea.begin).z)
|
||||
|
||||
# set_roads(skeleton_mountain, origin)
|
||||
# set_roads(skeleton_highway, origin)
|
||||
# set_roads_grids(road_grid, origin)
|
||||
# roads.setRoads(skeleton_mountain)
|
||||
# roads.setRoads(skeleton_highway)
|
||||
# remove_trees('./world_maker/data/heightmap.png', './world_maker/data/treemap.png',
|
||||
# './world_maker/data/smooth_sobel_watermap.png')
|
||||
# smooth_terrain('./world_maker/data/heightmap.png',
|
||||
# './world_maker/data/heightmap_smooth.png', './world_maker/data/smooth_sobel_watermap.png')
|
||||
|
||||
blocks = {
|
||||
"wall": "blackstone",
|
||||
"roof": "blackstone",
|
||||
"roof_slab": "blackstone_slab",
|
||||
"door": "oak_door",
|
||||
"window": "glass_pane",
|
||||
"entrance": "oak_door",
|
||||
"stairs": "quartz_stairs",
|
||||
"stairs_slab": "quartz_slab",
|
||||
"celling": "quartz_block",
|
||||
"floor": "quartz_block",
|
||||
"celling_slab": "quartz_slab",
|
||||
"garden_outline": "oak_leaves",
|
||||
"garden_floor": "grass_block"
|
||||
}
|
||||
# # set_roads(skeleton_mountain, origin)
|
||||
# # set_roads(skeleton_highway, origin)
|
||||
# # set_roads_grids(road_grid, origin)
|
||||
# # roads.setRoads(skeleton_mountain)
|
||||
# # roads.setRoads(skeleton_highway)
|
||||
|
||||
entranceDirection = ["N", "S", "E", "W"]
|
||||
# blocks = {
|
||||
# "wall": "blackstone",
|
||||
# "roof": "blackstone",
|
||||
# "roof_slab": "blackstone_slab",
|
||||
# "door": "oak_door",
|
||||
# "window": "glass_pane",
|
||||
# "entrance": "oak_door",
|
||||
# "stairs": "quartz_stairs",
|
||||
# "stairs_slab": "quartz_slab",
|
||||
# "celling": "quartz_block",
|
||||
# "floor": "quartz_block",
|
||||
# "celling_slab": "quartz_slab",
|
||||
# "garden_outline": "oak_leaves",
|
||||
# "garden_floor": "grass_block"
|
||||
# }
|
||||
|
||||
for houses in rectangle_building:
|
||||
start = (houses[0][0]+buildArea.begin[0], houses[0]
|
||||
[1], houses[0][2]+buildArea.begin[2])
|
||||
end = (houses[1][0]+buildArea.begin[0], houses[1]
|
||||
[1], houses[1][2]+buildArea.begin[2])
|
||||
house = House(editor, start, end,
|
||||
entranceDirection[random.randint(0, 3)], blocks)
|
||||
house.build()
|
||||
# entranceDirection = ["N", "S", "E", "W"]
|
||||
|
||||
for houses in rectangle_house_mountain:
|
||||
start = (houses[0][0]+buildArea.begin[0], houses[0]
|
||||
[1], houses[0][2]+buildArea.begin[2])
|
||||
end = (houses[1][0]+buildArea.begin[0], houses[1]
|
||||
[1], houses[1][2]+buildArea.begin[2])
|
||||
house = House(editor, start, end,
|
||||
entranceDirection[random.randint(0, 3)], blocks)
|
||||
house.build()
|
||||
# for houses in rectangle_building:
|
||||
# start = (houses[0][0]+buildArea.begin[0], houses[0]
|
||||
# [1], houses[0][2]+buildArea.begin[2])
|
||||
# end = (houses[1][0]+buildArea.begin[0], houses[1]
|
||||
# [1], houses[1][2]+buildArea.begin[2])
|
||||
# house = House(editor, start, end,
|
||||
# entranceDirection[random.randint(0, 3)], blocks)
|
||||
# house.build()
|
||||
|
||||
# for houses in rectangle_house_mountain:
|
||||
# start = (houses[0][0]+buildArea.begin[0], houses[0]
|
||||
# [1], houses[0][2]+buildArea.begin[2])
|
||||
# end = (houses[1][0]+buildArea.begin[0], houses[1]
|
||||
# [1], houses[1][2]+buildArea.begin[2])
|
||||
# house = House(editor, start, end,
|
||||
# entranceDirection[random.randint(0, 3)], blocks)
|
||||
# house.build()
|
||||
|
||||
|
||||
def set_roads_grids(road_grid: Road_grid, origin):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from math import cos, pi, sin
|
||||
from typing import List
|
||||
from typing import List, Dict
|
||||
|
||||
import numpy as np
|
||||
|
||||
@@ -17,6 +17,9 @@ class Circle:
|
||||
self.outer = None
|
||||
self.points_thick: List[Point2D] = []
|
||||
|
||||
self.points_thick_by_line: List[List[Point2D]] = []
|
||||
self.gaps: List[Point2D] = []
|
||||
|
||||
self.spaced_radius = None
|
||||
self.spaced_points: List[Point2D] = []
|
||||
|
||||
@@ -24,6 +27,7 @@ class Circle:
|
||||
return f"Circle(center: {self.center}, radius: {self.radius}, spaced_radius: {self.spaced_radius}, inner: {self.inner}, outer: {self.outer})"
|
||||
|
||||
def circle(self, radius: int) -> List[Point2D]:
|
||||
self.points = []
|
||||
self.radius = radius
|
||||
center = self.center.copy()
|
||||
|
||||
@@ -48,8 +52,59 @@ class Circle:
|
||||
break
|
||||
return self.points
|
||||
|
||||
def circle_thick_by_line(self, inner: int, outter: int) -> List[List[Point2D]]:
|
||||
width = outter - inner
|
||||
self.circle_thick_by_line = [[] for _ in range(width)]
|
||||
for i in range(width):
|
||||
self.circle_thick_by_line[i] = self.circle(inner + i)
|
||||
if i > 0:
|
||||
self.gaps.append(Circle._remove_gaps(
|
||||
self.circle_thick_by_line[i], self.circle_thick_by_line[i-1]))
|
||||
return self.circle_thick_by_line, self.gaps
|
||||
|
||||
@staticmethod
|
||||
def _remove_gaps(outter_line: List[Point2D], inner_line: List[Point2D]) -> List[Point2D]:
|
||||
gaps = []
|
||||
for i in range(len(outter_line)):
|
||||
if Circle._count_neighbors(outter_line[i], inner_line) == 0:
|
||||
if Circle._count_neighbors(Point2D(outter_line[i].x-1, outter_line[i].y), inner_line) > 1:
|
||||
if Point2D(outter_line[i].x-1, outter_line[i].y) not in outter_line:
|
||||
gaps.append(
|
||||
Point2D(outter_line[i].x-1, outter_line[i].y))
|
||||
if Circle._count_neighbors(Point2D(outter_line[i].x+1, outter_line[i].y), inner_line) > 1:
|
||||
if Point2D(outter_line[i].x+1, outter_line[i].y) not in outter_line:
|
||||
gaps.append(
|
||||
Point2D(outter_line[i].x+1, outter_line[i].y))
|
||||
if Circle._count_neighbors(Point2D(outter_line[i].x, outter_line[i].y-1), inner_line) > 1:
|
||||
if Point2D(outter_line[i].x, outter_line[i].y-1) not in outter_line:
|
||||
gaps.append(
|
||||
Point2D(outter_line[i].x, outter_line[i].y-1))
|
||||
if Circle._count_neighbors(Point2D(outter_line[i].x, outter_line[i].y+1), inner_line) > 1:
|
||||
if Point2D(outter_line[i].x, outter_line[i].y+1) not in outter_line:
|
||||
gaps.append(
|
||||
Point2D(outter_line[i].x, outter_line[i].y+1))
|
||||
return gaps
|
||||
|
||||
@ staticmethod
|
||||
def _count_neighbors(point: Point2D, line: List[Point2D]) -> int:
|
||||
neighbors = 0
|
||||
for i in range(len(line)):
|
||||
if point.x == line[i].x:
|
||||
if point.y == line[i].y:
|
||||
return 0
|
||||
if point.y-1 == line[i].y:
|
||||
neighbors += 1
|
||||
if point.y+1 == line[i].y:
|
||||
neighbors += 1
|
||||
if point.y == line[i].y:
|
||||
if point.x-1 == line[i].x:
|
||||
neighbors += 1
|
||||
if point.x+1 == line[i].x:
|
||||
neighbors += 1
|
||||
return neighbors
|
||||
|
||||
def circle_thick(self, inner: int, outer: int) -> List[Point2D]:
|
||||
"""Compute discrete value of a 2d-circle with thickness.
|
||||
"""Compute discrete value of a 2d-circle with thickness.
|
||||
|
||||
From: https://stackoverflow.com/questions/27755514/circle-with-thickness-drawing-algorithm
|
||||
|
||||
@@ -108,7 +163,7 @@ class Circle:
|
||||
From: https://stackoverflow.com/questions/8487893/generate-all-the-points-on-the-circumference-of-a-circle
|
||||
|
||||
Args:
|
||||
number (int): Number of coordinates to be returned.
|
||||
number (int): Number of coordinates to be returned.
|
||||
radius (int): Radius of the circle.
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -12,12 +12,13 @@ class Segment2D:
|
||||
self.end = end
|
||||
self.points: List[Point2D] = []
|
||||
self.points_thick: List[Point2D] = []
|
||||
self.points_thick_by_line: List[Union[Point2D, int]] = []
|
||||
self.thickness = None
|
||||
|
||||
def __repr__(self):
|
||||
return str(f"Segment2D(start: {self.start}, end: {self.end}, points: {self.points})")
|
||||
|
||||
def segment(self, start: Point2D = None, end: Point2D = None, overlap: LINE_OVERLAP = LINE_OVERLAP.NONE, _is_computing_thickness: bool = False) -> Union[List[Point2D], None]:
|
||||
def segment(self, start: Point2D = None, end: Point2D = None, overlap: LINE_OVERLAP = LINE_OVERLAP.NONE, _is_computing_thickness: int = 0) -> Union[List[Point2D], None]:
|
||||
"""Modified Bresenham draw (line) with optional overlap.
|
||||
|
||||
From: https://github.com/ArminJo/Arduino-BlueDisplay/blob/master/src/LocalGUI/ThickLine.hpp
|
||||
@@ -108,6 +109,8 @@ class Segment2D:
|
||||
|
||||
>>> self.compute_thick_segment(self.start, self.end, self.thickness, self.thickness_mode)
|
||||
"""
|
||||
self.points_thick_by_line = [[] for _ in range(thickness+1)]
|
||||
|
||||
start = self.start.copy()
|
||||
end = self.end.copy()
|
||||
|
||||
@@ -158,7 +161,7 @@ class Segment2D:
|
||||
error += delta_2x
|
||||
|
||||
self.segment(
|
||||
start, end, overlap=LINE_OVERLAP.NONE, _is_computing_thickness=True)
|
||||
start, end, overlap=LINE_OVERLAP.NONE, _is_computing_thickness=1)
|
||||
|
||||
error = delta_2x - delta_x
|
||||
for i in range(thickness, 1, -1):
|
||||
@@ -173,7 +176,7 @@ class Segment2D:
|
||||
error += delta_2y
|
||||
|
||||
self.segment(
|
||||
start, end, overlap=overlap, _is_computing_thickness=True)
|
||||
start, end, overlap=overlap, _is_computing_thickness=i)
|
||||
|
||||
else:
|
||||
if swap:
|
||||
@@ -194,7 +197,7 @@ class Segment2D:
|
||||
error += delta_2x
|
||||
|
||||
self.segment(
|
||||
start, end, overlap=LINE_OVERLAP.NONE, _is_computing_thickness=True)
|
||||
start, end, overlap=LINE_OVERLAP.NONE, _is_computing_thickness=1)
|
||||
|
||||
error = delta_2x - delta_y
|
||||
for i in range(thickness, 1, -1):
|
||||
@@ -209,7 +212,7 @@ class Segment2D:
|
||||
error += delta_2x
|
||||
|
||||
self.segment(
|
||||
start, end, overlap=overlap, _is_computing_thickness=True)
|
||||
start, end, overlap=overlap, _is_computing_thickness=i)
|
||||
|
||||
return self.points_thick
|
||||
|
||||
@@ -241,7 +244,9 @@ class Segment2D:
|
||||
)
|
||||
|
||||
def _add_points(self, points, is_computing_thickness):
|
||||
if is_computing_thickness:
|
||||
if is_computing_thickness > 0:
|
||||
self.points_thick.append(points.copy())
|
||||
self.points_thick_by_line[is_computing_thickness].append(
|
||||
(points.copy()))
|
||||
else:
|
||||
self.points.append(points.copy())
|
||||
|
||||
@@ -62,8 +62,30 @@ class Road:
|
||||
# Get nearest in x,z projection
|
||||
nearest = self.polyline.segments[i].points_thick[j].nearest(
|
||||
Point3D.to_2d(self.polyline_total_line_output, removed_axis='y'), True)
|
||||
self.output_block.append(
|
||||
(Point3D.insert_3d([self.polyline.segments[i].points_thick[j]], 'y', [self.polyline_total_line_output[nearest[0]].y])[0].coordinates, Block("stone")))
|
||||
# self.output_block.append(
|
||||
# (Point3D.insert_3d([self.polyline.segments[i].points_thick[j]], 'y', [self.polyline_total_line_output[nearest[0]].y])[0].coordinates, Block("stone")))
|
||||
for k in range(len(self.polyline.segments[i].points_thick_by_line)):
|
||||
match k:
|
||||
case 0:
|
||||
blob = 'black_concrete'
|
||||
case 1:
|
||||
blob = 'red_concrete'
|
||||
case 2:
|
||||
blob = 'orange_concrete'
|
||||
case 3:
|
||||
blob = 'yellow_concrete'
|
||||
case 4:
|
||||
blob = 'green_concrete'
|
||||
case 5:
|
||||
blob = 'blue_concrete'
|
||||
case 6:
|
||||
blob = 'purple_concrete'
|
||||
|
||||
for m in range(len(self.polyline.segments[i].points_thick_by_line[k])):
|
||||
nearest = self.polyline.segments[i].points_thick_by_line[k][m].nearest(
|
||||
Point3D.to_2d(self.polyline_total_line_output, removed_axis='y'), True)
|
||||
self.output_block.append(
|
||||
(Point3D.insert_3d([self.polyline.segments[i].points_thick_by_line[k][m]], 'y', [self.polyline_total_line_output[nearest[0]].y])[0].coordinates, Block(blob)))
|
||||
|
||||
for i in range(1, len(self.polyline.centers)-1):
|
||||
# Circle
|
||||
|
||||
|
Before Width: | Height: | Size: 255 B After Width: | Height: | Size: 117 B |
|
Before Width: | Height: | Size: 311 B After Width: | Height: | Size: 89 B |
|
Before Width: | Height: | Size: 972 B After Width: | Height: | Size: 418 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 766 B |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 194 B |
|
Before Width: | Height: | Size: 825 B After Width: | Height: | Size: 608 B |
|
Before Width: | Height: | Size: 604 B After Width: | Height: | Size: 121 B |
|
Before Width: | Height: | Size: 540 B After Width: | Height: | Size: 322 B |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 292 B After Width: | Height: | Size: 290 B |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 354 B After Width: | Height: | Size: 505 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 627 B |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 569 B |
|
Before Width: | Height: | Size: 101 B After Width: | Height: | Size: 208 B |