I know this topic has a solution, but i was too deep working on this to stop. so…
A solution with no titleblock modification (Still seems to have some quirks i can’t quite work out or certain types of titleblocks :))
Python - ℗ | LargestRectangleCenter.FromLines
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
from math import sqrt
from operator import itemgetter
# Assuming 'curves' is your list of Curve elements
curves = IN[0]
def is_almost_equal(pt1, pt2, tolerance):
return pt1.DistanceTo(pt2) < tolerance
points = []
for i in range(len(curves)):
for j in range(i+1, len(curves)):
intersection = Geometry.Intersect(curves[i], curves[j])
if intersection:
points.extend([pt for pt in intersection if isinstance(pt, Point)])
# Removing duplicates
tolerance = 0.01 # Tolerance for considering points as duplicates
unique_points = []
for pt in points:
if not any(is_almost_equal(pt, p, tolerance) for p in unique_points):
unique_points.append(pt)
_pts = unique_points
def hull(_pts):
def pCrs(o, a, b):
return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
pts = sorted( (p.X, p.Y) for p in _pts)
pLen = len(pts)
if pLen < 4 : return pts
else:
lower, upper = [], []
for i in range(pLen):
j = pLen - 1 - i
while len(lower) >= 2 and pCrs(lower[-2], lower[-1], pts[i]) <= 0.000001:
lower.pop()
lower.append(pts[i])
while len(upper) >= 2 and pCrs(upper[-2], upper[-1], pts[j]) <= 0.000001:
upper.pop()
upper.append(pts[j])
lower.pop()
upper.pop()
lower.extend(upper)
return lower
def scalar(k, i, j):
return k[0] * (i[1] - j[1]) + k[1] * (j[0] - i[0]) + j[1] * i[0] - i[1] * j[0]
def pDist(a, b, sqrt=sqrt):
return sqrt( (a[0] - b[0])**2 + (a[1] - b[1])**2)
def linDist(a, b, p):
line_dist = pDist(a, b)
if line_dist == 0:
return a, pDist(p, a)
t = ( (p[0] - a[0]) * (b[0] - a[0]) + (p[1] - a[1]) * (b[1] - a[1]) ) / line_dist**2
cp = ( (b[0] - a[0]) * t + a[0], (b[1] - a[1]) * t + a[1])
d1 = pDist(p, cp)
return cp, d1
def indexer(end, position=0, start=0, step=1):
i = position - step
while True:
i += step
if i >= end:
i = start
yield i
def highSearch(pts, iPt, jPt, j, it1=None, k=None, m=None,
indexer=indexer, scalar=scalar):
if it1 is None:
it1 = indexer(len(pts), j)
k, m = next(it1), next(it1)
Sa = scalar(pts[k], iPt, jPt)
Sb = scalar(pts[m], iPt, jPt)
while Sa < Sb:
k, m = m, next(it1)
Sa = scalar(pts[k], iPt, jPt)
Sb = scalar(pts[m], iPt, jPt)
return k, m
pts = hull(_pts)
OUT = []
highPts, closePts, areas, dists = [], [], [], []
lnPts = len(pts)
it1 = indexer(lnPts, 2)
k, m = next(it1), next(it1)
for i in range(lnPts):
j = (i + 1) % lnPts
k, m = highSearch(pts, pts[i], pts[j], j+1, it1, k, m)
highPts.append(pts[k])
cp, l1 = linDist(pts[i], pts[j], pts[k])
closePts.append(cp)
n, _ = highSearch(pts, pts[k], cp, j)
_, l2a = linDist(pts[k], cp, pts[n])
q, _ = highSearch(pts, cp, pts[k], m)
_, l2b = linDist(cp, pts[k], pts[q])
areas.append(l1 * (l2a + l2b) )
dists.append( (l2a, l2b) )
ix, _ = min(enumerate(areas), key=itemgetter(1) )
d1, d2 = dists[ix]
_a, _b = closePts[ix], highPts[ix]
a = Point.ByCoordinates(_a[0], _a[1], 0)
b = Point.ByCoordinates(_b[0], _b[1], 0)
_v = Vector.ByTwoPoints(a, b)
v = Vector.ByCoordinates(-_v.Y, _v.X, 0).Normalized()
p1 = a.Add(v.Scale(d2) )
p2 = a.Subtract(v.Scale(d1) )
p3 = b.Subtract(v.Scale(d1) )
p4 = b.Add(v.Scale(d2) )
# Calculate the center point of the rectangle
center_x = (p1.X + p2.X + p3.X + p4.X) / 4
center_y = (p1.Y + p2.Y + p3.Y + p4.Y) / 4
# Create the center point
center_point = Point.ByCoordinates(center_x, center_y, 0)
# Output the center point instead of the rectangle
OUT = center_point
Python - ℗ | ClosestLine +Y, -Y, +X, -X From Point
class Point:
def __init__(self, X, Y, Z):
self.X = X
self.Y = Y
self.Z = Z
class Vector:
def __init__(self, X, Y, Z, Length):
self.X = X
self.Y = Y
self.Z = Z
self.Length = Length
class Line:
def __init__(self, StartPoint, EndPoint, Direction):
self.StartPoint = StartPoint
self.EndPoint = EndPoint
self.Direction = Direction
def closest_lines(point, lines):
min_dist = {'+X': float('inf'), '-X': float('inf'), '+Y': float('inf'), '-Y': float('inf')}
closest_lines = {'+X': None, '-X': None, '+Y': None, '-Y': None}
for line in lines:
# Calculate the intersection point of the line with the +X ray
if line.Direction.X > 0:
t = (point.X - line.StartPoint.X) / line.Direction.X
if 0 <= t <= 1: # Check if the intersection is within the line segment
intersection = Point(line.StartPoint.X + t * line.Direction.X, line.StartPoint.Y + t * line.Direction.Y, 0)
dist = ((intersection.X - point.X)**2 + (intersection.Y - point.Y)**2)**0.5
if dist < min_dist['+X']:
min_dist['+X'] = dist
closest_lines['+X'] = line
# Repeat for the other directions
# -X
elif line.Direction.X < 0:
t = (point.X - line.StartPoint.X) / line.Direction.X
if 0 <= t <= 1: # Check if the intersection is within the line segment
intersection = Point(line.StartPoint.X + t * line.Direction.X, line.StartPoint.Y + t * line.Direction.Y, 0)
dist = ((intersection.X - point.X)**2 + (intersection.Y - point.Y)**2)**0.5
if dist < min_dist['-X']:
min_dist['-X'] = dist
closest_lines['-X'] = line
# +Y
if line.Direction.Y > 0:
t = (point.Y - line.StartPoint.Y) / line.Direction.Y
if 0 <= t <= 1: # Check if the intersection is within the line segment
intersection = Point(line.StartPoint.X + t * line.Direction.X, line.StartPoint.Y + t * line.Direction.Y, 0)
dist = ((intersection.X - point.X)**2 + (intersection.Y - point.Y)**2)**0.5
if dist < min_dist['+Y']:
min_dist['+Y'] = dist
closest_lines['+Y'] = line
# -Y
elif line.Direction.Y < 0:
t = (point.Y - line.StartPoint.Y) / line.Direction.Y
if 0 <= t <= 1: # Check if the intersection is within the line segment
intersection = Point(line.StartPoint.X + t * line.Direction.X, line.StartPoint.Y + t * line.Direction.Y, 0)
dist = ((intersection.X - point.X)**2 + (intersection.Y - point.Y)**2)**0.5
if dist < min_dist['-Y']:
min_dist['-Y'] = dist
closest_lines['-Y'] = line
# Return the results as a list
return [closest_lines[key] for key in ['+X', '-X', '+Y', '-Y'] if closest_lines[key] is not None]
point = IN[1]
lines = IN[0]
result = closest_lines(point, lines)
OUT = result