From a50fc34ed2a456264172a7ee4f70bb7cb6322f8c Mon Sep 17 00:00:00 2001 From: Xeon0X Date: Tue, 11 Jun 2024 01:57:42 +0200 Subject: [PATCH] Create even more objects --- networks/geometry/Circle.py | 2 +- networks/geometry/Enums.py | 13 +++ networks/geometry/Polyline.py | 2 +- networks/geometry/Segment2D.py | 183 +++++++++++++++++++++++++++++++++ networks/geometry/Segment3D.py | 10 ++ 5 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 networks/geometry/Enums.py create mode 100644 networks/geometry/Segment2D.py create mode 100644 networks/geometry/Segment3D.py diff --git a/networks/geometry/Circle.py b/networks/geometry/Circle.py index 50c153e..117f556 100644 --- a/networks/geometry/Circle.py +++ b/networks/geometry/Circle.py @@ -1,5 +1,5 @@ from typing import Type -import Point2D +from networks.geometry.Point2D import Point2D class Circle: diff --git a/networks/geometry/Enums.py b/networks/geometry/Enums.py new file mode 100644 index 0000000..dce1267 --- /dev/null +++ b/networks/geometry/Enums.py @@ -0,0 +1,13 @@ +from enum import Enum + + +class LINE_OVERLAP(Enum): + NONE = 0 + MAJOR = 1 + MINOR = 2 + + +class LINE_THICKNESS_MODE(Enum): + MIDDLE = 0 + DRAW_COUNTERCLOCKWISE = 1 + DRAW_CLOCKWISE = 2 diff --git a/networks/geometry/Polyline.py b/networks/geometry/Polyline.py index ace65e5..39bae5c 100644 --- a/networks/geometry/Polyline.py +++ b/networks/geometry/Polyline.py @@ -1,5 +1,5 @@ from typing import Type -import Point2D +from networks.geometry.Point2D import Point2D from math import sqrt, inf import numpy as np diff --git a/networks/geometry/Segment2D.py b/networks/geometry/Segment2D.py new file mode 100644 index 0000000..98eb9c8 --- /dev/null +++ b/networks/geometry/Segment2D.py @@ -0,0 +1,183 @@ +from typing import Type +from networks.geometry.Enums import LINE_OVERLAP, LINE_THICKNESS_MODE +from networks.geometry.Point2D import Point2D + + +class Segment2D: + def __init__(start: Type[Point2D], end: Type[Point2D]): + self.start = start + self.end = end + self.coordinates = [] + + def draw_line_overlap(start: Type[Point2D], end: Type[Point2D], overlap: Type[LINE_OVERLAP]): + """Modified Bresenham draw (line) with optional overlap. + + From https://github.com/ArminJo/Arduino-BlueDisplay/blob/master/src/LocalGUI/ThickLine.hpp + + Args: + start (Type[Point2D]): Start point of the segment. + end (Type[Point2D]): End point of the segment. + overlap (Type[LINE_OVERLAP]): Overlap draws additional pixel when changing minor direction. For standard bresenham overlap, choose LINE_OVERLAP_NONE. Can also be LINE_OVERLAP_MAJOR or LINE_OVERLAP_MINOR. + """ + 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 + + self.coordinates.append(start) + + if (delta_x > delta_y): + error = delta_2y - delta_x + while (start.x != end.x): + start.x += step_x + if (error >= 0): + if (overlap == LINE_OVERLAP.MAJOR): + self.coordinates.append(start) + + start.y += step_y + if (overlap == LINE_OVERLAP.MINOR): + self.coordinates.append( + Point2D(start.x - step_x, start.y)) + error -= delta_2x + error += delta_2y + self.coordinates.append(start) + else: + error = delta_2x - delta_y + while (start.y != end.y): + start.y += step_y + if (error >= 0): + if (overlap == LINE_OVERLAP.MAJOR): + self.coordinates.append(start) + + start.x += step_x + if (overlap == LINE_OVERLAP.MINOR): + self.coordinates.append( + Point2D(start.x, start.y - step_y)) + error -= delta_2y + error += delta_2x + self.coordinates.append(start) + + def draw_thick_line(start: Type[Point2D], end: Type[Point2D], thickness: int, thickness_mode: Type[LINE_THICKNESS_MODE]): + """Bresenham with thickness. + + From https://github.com/ArminJo/Arduino-BlueDisplay/blob/master/src/LocalGUI/ThickLine.hpp + Probably inspired from Murphy's Modified Bresenham algorithm : http://zoo.co.uk/murphy/thickline/index.html + + Args: + start (Type[Point2D]): Start point of the segment. + end (Type[Point2D]): End point of the segment. + thickness (int): Total width of the surface. Placement relative to the original segment depends on thickness_mode. + thickness_mode (Type[LINE_THICKNESS_MODE]): Can be one of LINE_THICKNESS_MIDDLE, LINE_THICKNESS_DRAW_CLOCKWISE, LINE_THICKNESS_DRAW_COUNTERCLOCKWISE. + """ + delta_y = end.x - start.x + delta_x = end.y - start.y + + 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 + + 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): + + 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 + + draw_line_overlap(start, end, LINE_OVERLAP.NONE) + + error = delta_2x - delta_x + for i in range(thickness, 1, -1): + start.x += step_x + end.x += step_x + overlap = LINE_OVERLAP.NONE + if (error >= 0): + start.y += step_y + end.y += step_y + error -= delta_2x + overlap = LINE_OVERLAP.MAJOR + error += delta_2y + + draw_line_overlap(start, end, overlap) + + 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 + + draw_line_overlap(start, end, LINE_OVERLAP.NONE) + + error = delta_2x - delta_y + for i in range(thickness, 1, -1): + start.y += step_y + end.y += step_y + overlap = LINE_OVERLAP.NONE + if (error >= 0): + start.x += step_x + end.x += step_x + error -= delta_2y + overlap = LINE_OVERLAP.MAJOR + error += delta_2x + + draw_line_overlap(start, end, overlap) diff --git a/networks/geometry/Segment3D.py b/networks/geometry/Segment3D.py new file mode 100644 index 0000000..5179edb --- /dev/null +++ b/networks/geometry/Segment3D.py @@ -0,0 +1,10 @@ +from typing import Type +from networks.geometry.Enums import LINE_OVERLAP +from networks.geometry.Point3D import Point3D + + +class Segment3D: + def __init__(start: Type[Point3D], end: Type[Point3D]): + self.start = start + self.end = end + self.coordinates = []