Add 3d objects
This commit is contained in:
17
networks/geometry/Point3D.py
Normal file
17
networks/geometry/Point3D.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from typing import Type
|
||||||
|
|
||||||
|
|
||||||
|
class Point3D:
|
||||||
|
def __init__(self, x: int, y: int, z: int):
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.z = z
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
return Point3D(self.x, self.y, self.z)
|
||||||
|
|
||||||
|
def coordinates(self):
|
||||||
|
return (self.x, self.y, self.z)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"Point2D(x: {self.x}, y: {self.y}, z: {self.z})"
|
||||||
@@ -9,7 +9,7 @@ class Segment2D:
|
|||||||
self.end = end
|
self.end = end
|
||||||
self.coordinates = []
|
self.coordinates = []
|
||||||
|
|
||||||
def draw_line_overlap(start: Type[Point2D], end: Type[Point2D], overlap: Type[LINE_OVERLAP]):
|
def compute_segment_overlap(start: Type[Point2D], end: Type[Point2D], overlap: Type[LINE_OVERLAP]):
|
||||||
"""Modified Bresenham draw (line) with optional overlap.
|
"""Modified Bresenham draw (line) with optional overlap.
|
||||||
|
|
||||||
From https://github.com/ArminJo/Arduino-BlueDisplay/blob/master/src/LocalGUI/ThickLine.hpp
|
From https://github.com/ArminJo/Arduino-BlueDisplay/blob/master/src/LocalGUI/ThickLine.hpp
|
||||||
@@ -74,7 +74,7 @@ class Segment2D:
|
|||||||
error += delta_2x
|
error += delta_2x
|
||||||
self.coordinates.append(start)
|
self.coordinates.append(start)
|
||||||
|
|
||||||
def draw_thick_line(start: Type[Point2D], end: Type[Point2D], thickness: int, thickness_mode: Type[LINE_THICKNESS_MODE]):
|
def compute_thick_segment(start: Type[Point2D], end: Type[Point2D], thickness: int, thickness_mode: Type[LINE_THICKNESS_MODE]):
|
||||||
"""Bresenham with thickness.
|
"""Bresenham with thickness.
|
||||||
|
|
||||||
From https://github.com/ArminJo/Arduino-BlueDisplay/blob/master/src/LocalGUI/ThickLine.hpp
|
From https://github.com/ArminJo/Arduino-BlueDisplay/blob/master/src/LocalGUI/ThickLine.hpp
|
||||||
|
|||||||
@@ -8,3 +8,96 @@ class Segment3D:
|
|||||||
self.start = start
|
self.start = start
|
||||||
self.end = end
|
self.end = end
|
||||||
self.coordinates = []
|
self.coordinates = []
|
||||||
|
|
||||||
|
def compute_segment(start: Type[Point3D], end: Type[Point3D], overlap=True):
|
||||||
|
"""Calculate a segment between two points in 3D space. 3d Bresenham algorithm.
|
||||||
|
|
||||||
|
From: https://www.geeksforgeeks.org/bresenhams-algorithm-for-3-d-line-drawing/
|
||||||
|
|
||||||
|
Args:
|
||||||
|
start (Type[Point3D]): First coordinates.
|
||||||
|
end (Type[Point3D]): Second coordinates.
|
||||||
|
overlap (bool, optional): If true, remove unnecessary coordinates connecting to other coordinates side by side, leaving only a diagonal connection. Defaults to True.
|
||||||
|
"""
|
||||||
|
self.coordinates.append(start)
|
||||||
|
dx = abs(end.x - start.x)
|
||||||
|
dy = abs(end.y - start.y)
|
||||||
|
dz = abs(end.z - start.z)
|
||||||
|
if end.x > start.x:
|
||||||
|
xs = 1
|
||||||
|
else:
|
||||||
|
xs = -1
|
||||||
|
if end.y > start.y:
|
||||||
|
ys = 1
|
||||||
|
else:
|
||||||
|
ys = -1
|
||||||
|
if end.z > start.z:
|
||||||
|
zs = 1
|
||||||
|
else:
|
||||||
|
zs = -1
|
||||||
|
|
||||||
|
# Driving axis is X-axis
|
||||||
|
if dx >= dy and dx >= dz:
|
||||||
|
p1 = 2 * dy - dx
|
||||||
|
p2 = 2 * dz - dx
|
||||||
|
while start.x != end.x:
|
||||||
|
start.x += xs
|
||||||
|
self.coordinates.append(start)
|
||||||
|
if p1 >= 0:
|
||||||
|
start.y += ys
|
||||||
|
if not overlap:
|
||||||
|
if self.coordinates[-1].y != start.y:
|
||||||
|
self.coordinates.append(start)
|
||||||
|
p1 -= 2 * dx
|
||||||
|
if p2 >= 0:
|
||||||
|
start.z += zs
|
||||||
|
if not overlap:
|
||||||
|
if self.coordinates[-1].z != start.z:
|
||||||
|
self.coordinates.append(start)
|
||||||
|
p2 -= 2 * dx
|
||||||
|
p1 += 2 * dy
|
||||||
|
p2 += 2 * dz
|
||||||
|
|
||||||
|
# Driving axis is Y-axis
|
||||||
|
elif dy >= dx and dy >= dz:
|
||||||
|
p1 = 2 * dx - dy
|
||||||
|
p2 = 2 * dz - dy
|
||||||
|
while start.y != end.y:
|
||||||
|
start.y += ys
|
||||||
|
self.coordinates.append(start)
|
||||||
|
if p1 >= 0:
|
||||||
|
start.x += xs
|
||||||
|
if not overlap:
|
||||||
|
if self.coordinates[-1].x != start.x:
|
||||||
|
self.coordinates.append(start)
|
||||||
|
p1 -= 2 * dy
|
||||||
|
if p2 >= 0:
|
||||||
|
start.z += zs
|
||||||
|
if not overlap:
|
||||||
|
if self.coordinates[-1].z != start.z:
|
||||||
|
self.coordinates.append(start)
|
||||||
|
p2 -= 2 * dy
|
||||||
|
p1 += 2 * dx
|
||||||
|
p2 += 2 * dz
|
||||||
|
|
||||||
|
# Driving axis is Z-axis
|
||||||
|
else:
|
||||||
|
p1 = 2 * dy - dz
|
||||||
|
p2 = 2 * dx - dz
|
||||||
|
while start.z != end.z:
|
||||||
|
start.z += zs
|
||||||
|
self.coordinates.append(start)
|
||||||
|
if p1 >= 0:
|
||||||
|
start.y += ys
|
||||||
|
if not overlap:
|
||||||
|
if self.coordinates[-1].y != start.y:
|
||||||
|
self.coordinates.append(start)
|
||||||
|
p1 -= 2 * dz
|
||||||
|
if p2 >= 0:
|
||||||
|
start.x += xs
|
||||||
|
if not overlap:
|
||||||
|
if self.coordinates[-1].x != start.x:
|
||||||
|
self.coordinates.append(start)
|
||||||
|
p2 -= 2 * dz
|
||||||
|
p1 += 2 * dy
|
||||||
|
p2 += 2 * dx
|
||||||
|
|||||||
322
networks/test.py
322
networks/test.py
@@ -1,322 +0,0 @@
|
|||||||
from gdpc import Editor, Block, geometry
|
|
||||||
from enum import Enum
|
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
def circle(xm, ym, r, pixel_perfect=True):
|
|
||||||
editor = Editor(buffering=True)
|
|
||||||
block = random.choices(("white_concrete", "red_concrete", "blue_concrete", "green_concrete",
|
|
||||||
"yellow_concrete", "black_concrete", "purple_concrete", "pink_concrete"))[0]
|
|
||||||
x = -r
|
|
||||||
y = 0
|
|
||||||
err = 2-2*r
|
|
||||||
while (True):
|
|
||||||
editor.placeBlock((xm-x, 141, ym+y),
|
|
||||||
Block(block))
|
|
||||||
editor.placeBlock((xm-y, 141, ym-x),
|
|
||||||
Block(block))
|
|
||||||
editor.placeBlock((xm+x, 141, ym-y),
|
|
||||||
Block(block))
|
|
||||||
editor.placeBlock((xm+y, 141, ym+x),
|
|
||||||
Block(block))
|
|
||||||
print(xm-x, ym+y)
|
|
||||||
print(xm-y, ym-x)
|
|
||||||
print(xm+x, ym-y)
|
|
||||||
print(xm+y, ym+x)
|
|
||||||
r = err
|
|
||||||
update = False
|
|
||||||
if (r <= y):
|
|
||||||
y += 1
|
|
||||||
update = True
|
|
||||||
err += y*2+1
|
|
||||||
if ((r > x or err > y)):
|
|
||||||
if (pixel_perfect == True or update == False):
|
|
||||||
x += 1
|
|
||||||
err += x*2+1
|
|
||||||
update = True
|
|
||||||
if (x < 0):
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
def set_pixel(x, y, colour):
|
|
||||||
editor = Editor(buffering=True)
|
|
||||||
editor.placeBlock((x, 160, y),
|
|
||||||
Block(colour))
|
|
||||||
|
|
||||||
|
|
||||||
def x_line(x1, x2, y, colour):
|
|
||||||
while x1 <= x2:
|
|
||||||
set_pixel(x1, y, colour)
|
|
||||||
x1 += 1
|
|
||||||
|
|
||||||
|
|
||||||
def y_line(x, y1, y2, colour):
|
|
||||||
while y1 <= y2:
|
|
||||||
set_pixel(x, y1, colour)
|
|
||||||
y1 += 1
|
|
||||||
|
|
||||||
|
|
||||||
def circle2(xc, yc, inner, outer):
|
|
||||||
# https://stackoverflow.com/questions/27755514/circle-with-thickness-drawing-algorithm
|
|
||||||
xo = outer
|
|
||||||
xi = inner
|
|
||||||
y = 0
|
|
||||||
erro = 1 - xo
|
|
||||||
erri = 1 - xi
|
|
||||||
|
|
||||||
while xo >= y:
|
|
||||||
colour = random.choices(("white_concrete", "red_concrete", "blue_concrete", "green_concrete",
|
|
||||||
"yellow_concrete", "black_concrete", "purple_concrete", "pink_concrete"))[0]
|
|
||||||
x_line(xc + xi, xc + xo, yc + y, colour)
|
|
||||||
y_line(xc + y, yc + xi, yc + xo, colour)
|
|
||||||
x_line(xc - xo, xc - xi, yc + y, colour)
|
|
||||||
y_line(xc - y, yc + xi, yc + xo, colour)
|
|
||||||
x_line(xc - xo, xc - xi, yc - y, colour)
|
|
||||||
y_line(xc - y, yc - xo, yc - xi, colour)
|
|
||||||
x_line(xc + xi, xc + xo, yc - y, colour)
|
|
||||||
y_line(xc + y, yc - xo, yc - xi, colour)
|
|
||||||
|
|
||||||
y += 1
|
|
||||||
|
|
||||||
if erro < 0:
|
|
||||||
erro += 2 * y + 1
|
|
||||||
else:
|
|
||||||
xo -= 1
|
|
||||||
erro += 2 * (y - xo + 1)
|
|
||||||
|
|
||||||
if y > inner:
|
|
||||||
xi = y
|
|
||||||
else:
|
|
||||||
if erri < 0:
|
|
||||||
erri += 2 * y + 1
|
|
||||||
else:
|
|
||||||
xi -= 1
|
|
||||||
erri += 2 * (y - xi + 1)
|
|
||||||
|
|
||||||
|
|
||||||
# print("\n")
|
|
||||||
# circle2(-1606, 758, 5, 15)
|
|
||||||
# circle2(-1606, 758, 5, 5)
|
|
||||||
# circle2(-1606, 758, 10, 10)
|
|
||||||
circle2(-1606, 758, 15, 17)
|
|
||||||
|
|
||||||
|
|
||||||
class LineOverlap(Enum):
|
|
||||||
NONE = 0
|
|
||||||
MAJOR = 1
|
|
||||||
MINOR = 2
|
|
||||||
|
|
||||||
|
|
||||||
class LineThicknessMode(Enum):
|
|
||||||
MIDDLE = 0
|
|
||||||
DRAW_COUNTERCLOCKWISE = 1
|
|
||||||
DRAW_CLOCKWISE = 2
|
|
||||||
|
|
||||||
|
|
||||||
class Point2D:
|
|
||||||
def __init__(self, x, y):
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"({self.x} {self.y})"
|
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
return Point2D(self.x, self.y)
|
|
||||||
|
|
||||||
def get_coordinates(self):
|
|
||||||
return (self.x, self.y)
|
|
||||||
|
|
||||||
|
|
||||||
def drawLineOverlap(start, end, overlap):
|
|
||||||
y = 120
|
|
||||||
block = random.choices(("white_concrete", "red_concrete", "blue_concrete", "green_concrete",
|
|
||||||
"yellow_concrete", "black_concrete", "purple_concrete", "pink_concrete"))[0]
|
|
||||||
print(block)
|
|
||||||
editor = Editor(buffering=True)
|
|
||||||
|
|
||||||
start = start.copy()
|
|
||||||
end = end.copy()
|
|
||||||
|
|
||||||
# Direction
|
|
||||||
delta_x = end.x - start.x
|
|
||||||
delta_y = end.y - start.y
|
|
||||||
|
|
||||||
if (delta_x < 0):
|
|
||||||
delta_x = -delta_x
|
|
||||||
step_x = -1
|
|
||||||
else:
|
|
||||||
step_x = +1
|
|
||||||
|
|
||||||
if (delta_y < 0):
|
|
||||||
delta_y = -delta_y
|
|
||||||
step_y = -1
|
|
||||||
else:
|
|
||||||
step_y = +1
|
|
||||||
|
|
||||||
delta_2x = 2*delta_x
|
|
||||||
delta_2y = 2*delta_y
|
|
||||||
|
|
||||||
print(start.x, start.y)
|
|
||||||
editor.placeBlock((start.x, y, start.y), Block(block))
|
|
||||||
|
|
||||||
if (delta_x > delta_y):
|
|
||||||
error = delta_2y - delta_x
|
|
||||||
while (start.x != end.x):
|
|
||||||
start.x += step_x
|
|
||||||
if (error >= 0):
|
|
||||||
if (overlap == LineOverlap.MAJOR):
|
|
||||||
print(start.x, start.y)
|
|
||||||
editor.placeBlock((start.x, y, start.y),
|
|
||||||
Block(block))
|
|
||||||
|
|
||||||
start.y += step_y
|
|
||||||
if (overlap == LineOverlap.MINOR):
|
|
||||||
print(start.x - step_x, start.y)
|
|
||||||
editor.placeBlock((start.x - step_x, y, start.y),
|
|
||||||
Block(block))
|
|
||||||
error -= delta_2x
|
|
||||||
error += delta_2y
|
|
||||||
print(start.x, start.y)
|
|
||||||
editor.placeBlock((start.x, y, start.y),
|
|
||||||
Block(block))
|
|
||||||
else:
|
|
||||||
error = delta_2x - delta_y
|
|
||||||
while (start.y != end.y):
|
|
||||||
start.y += step_y
|
|
||||||
if (error >= 0):
|
|
||||||
if (overlap == LineOverlap.MAJOR):
|
|
||||||
print(start)
|
|
||||||
editor.placeBlock((start.x, y, start.y),
|
|
||||||
Block(block))
|
|
||||||
start.x += step_x
|
|
||||||
if (overlap == LineOverlap.MINOR):
|
|
||||||
print(start.x, start.y - step.y, start.z, )
|
|
||||||
editor.placeBlock((start.x, y, start.y - step.y),
|
|
||||||
Block(block))
|
|
||||||
error -= delta_2y
|
|
||||||
error += delta_2x
|
|
||||||
print(start.x, start.y)
|
|
||||||
editor.placeBlock((start.x, y, start.y),
|
|
||||||
Block("white_concrete"))
|
|
||||||
|
|
||||||
|
|
||||||
# drawLineOverlap(Point2D(-10, 0, 0,), Point2D(10, 0, 3),
|
|
||||||
# LineOverlap.NONE)
|
|
||||||
|
|
||||||
|
|
||||||
def drawThickLine(start, end, thickness, thickness_mode):
|
|
||||||
delta_y = end.x - start.x
|
|
||||||
delta_x = end.y - start.y
|
|
||||||
|
|
||||||
print("START", start)
|
|
||||||
|
|
||||||
swap = True
|
|
||||||
if delta_x < 0:
|
|
||||||
delta_x = -delta_x
|
|
||||||
step_x = -1
|
|
||||||
swap = not swap
|
|
||||||
else:
|
|
||||||
step_x = +1
|
|
||||||
|
|
||||||
if (delta_y < 0):
|
|
||||||
delta_y = -delta_y
|
|
||||||
step_y = -1
|
|
||||||
swap = not swap
|
|
||||||
else:
|
|
||||||
step_y = +1
|
|
||||||
|
|
||||||
delta_2x = 2 * delta_x
|
|
||||||
delta_2y = 2 * delta_y
|
|
||||||
|
|
||||||
draw_start_adjust_count = int(thickness / 2)
|
|
||||||
if (thickness_mode == LineThicknessMode.DRAW_COUNTERCLOCKWISE):
|
|
||||||
draw_start_adjust_count = thickness - 1
|
|
||||||
elif (thickness_mode == LineThicknessMode.DRAW_CLOCKWISE):
|
|
||||||
draw_start_adjust_count = 0
|
|
||||||
print("START", start)
|
|
||||||
if (delta_x >= delta_y):
|
|
||||||
if swap:
|
|
||||||
draw_start_adjust_count = (thickness - 1) - draw_start_adjust_count
|
|
||||||
step_y = -step_y
|
|
||||||
else:
|
|
||||||
step_x = -step_x
|
|
||||||
|
|
||||||
error = delta_2y - delta_x
|
|
||||||
for i in range(draw_start_adjust_count, 0, -1):
|
|
||||||
print("START", start)
|
|
||||||
start.x -= step_x
|
|
||||||
end.x -= step_x
|
|
||||||
if error >= 0:
|
|
||||||
start.y -= step_y
|
|
||||||
end.y -= step_y
|
|
||||||
error -= delta_2x
|
|
||||||
error += delta_2x
|
|
||||||
print("START", start)
|
|
||||||
print("First print")
|
|
||||||
print(start, end)
|
|
||||||
drawLineOverlap(start, end, LineOverlap.NONE)
|
|
||||||
print(start, end)
|
|
||||||
print("End print")
|
|
||||||
|
|
||||||
error = delta_2x - delta_x
|
|
||||||
for i in range(thickness, 1, -1):
|
|
||||||
start.x += step_x
|
|
||||||
end.x += step_x
|
|
||||||
overlap = LineOverlap.NONE
|
|
||||||
if (error >= 0):
|
|
||||||
start.y += step_y
|
|
||||||
end.y += step_y
|
|
||||||
error -= delta_2x
|
|
||||||
overlap = LineOverlap.MAJOR
|
|
||||||
error += delta_2y
|
|
||||||
print("Second print")
|
|
||||||
print(start, end)
|
|
||||||
drawLineOverlap(start, end, overlap)
|
|
||||||
print(start, end)
|
|
||||||
print("End print")
|
|
||||||
else:
|
|
||||||
if swap:
|
|
||||||
step_x = -step_x
|
|
||||||
else:
|
|
||||||
draw_start_adjust_count = (thickness - 1) - draw_start_adjust_count
|
|
||||||
step_y = -step_y
|
|
||||||
|
|
||||||
error = delta_2x - delta_y
|
|
||||||
for i in range(draw_start_adjust_count, 0, -1):
|
|
||||||
start.y -= step_y
|
|
||||||
end.y -= step_y
|
|
||||||
if (error >= 0):
|
|
||||||
start.x -= step_x
|
|
||||||
end.x -= step_x
|
|
||||||
error -= delta_2y
|
|
||||||
error += delta_2x
|
|
||||||
|
|
||||||
print("Third line")
|
|
||||||
print(start, end)
|
|
||||||
drawLineOverlap(start, end, LineOverlap.NONE)
|
|
||||||
print(start, end)
|
|
||||||
print("End line")
|
|
||||||
error = delta_2x - delta_y
|
|
||||||
for i in range(thickness, 1, -1):
|
|
||||||
start.y += step_y
|
|
||||||
end.y += step_y
|
|
||||||
overlap = LineOverlap.NONE
|
|
||||||
if (error >= 0):
|
|
||||||
start.x += step_x
|
|
||||||
end.x += step_x
|
|
||||||
error -= delta_2y
|
|
||||||
overlap = LineOverlap.MAJOR
|
|
||||||
error += delta_2x
|
|
||||||
print("Fourth line")
|
|
||||||
print(start, end)
|
|
||||||
drawLineOverlap(start, end, overlap)
|
|
||||||
print(start, end)
|
|
||||||
print("End")
|
|
||||||
|
|
||||||
|
|
||||||
print("SPACE\n\n")
|
|
||||||
drawThickLine(Point2D(-1681, 864), Point2D(-1804, 920),
|
|
||||||
21, LineThicknessMode.MIDDLE)
|
|
||||||
Reference in New Issue
Block a user