Skip to content

Instantly share code, notes, and snippets.

@stephensmitchell
Last active December 28, 2025 15:55
Show Gist options
  • Select an option

  • Save stephensmitchell/bcdb0f8528b6ea0c61cfb134b8b7dc14 to your computer and use it in GitHub Desktop.

Select an option

Save stephensmitchell/bcdb0f8528b6ea0c61cfb134b8b7dc14 to your computer and use it in GitHub Desktop.
# created with Alibre Script Genie by Stephen S. Mitchell, https://github.com/stephensmitchell
from __future__ import division
import sys
import math
from AlibreScript import *
ScriptName = "Batch Area Moments"
ScriptVersion = "1.0"
DIALOG_WIDTH = 400
CURVE_SEGMENTS = 144
VERTEX_TOLERANCE = 1e-6
CIRCUMFERENCE_TOLERANCE = 0.02
ARC_LENGTH_TOLERANCE = 0.05
CURVATURE_THRESHOLD = 1.05
def vec_subtract(a, b):
return [a[0]-b[0], a[1]-b[1], a[2]-b[2]]
def vec_add(a, b):
return [a[0]+b[0], a[1]+b[1], a[2]+b[2]]
def vec_scale(v, s):
return [v[0]*s, v[1]*s, v[2]*s]
def vec_cross(a, b):
return [a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]]
def vec_dot(a, b):
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]
def vec_length(v):
return math.sqrt(v[0]**2 + v[1]**2 + v[2]**2)
def vec_normalize(v):
L = vec_length(v)
if L < 1e-12:
return [0.0, 0.0, 0.0]
return [v[0]/L, v[1]/L, v[2]/L]
def vec_distance(a, b):
return math.sqrt((b[0]-a[0])**2 + (b[1]-a[1])**2 + (b[2]-a[2])**2)
def vec_midpoint(a, b):
return [(a[0]+b[0])/2.0, (a[1]+b[1])/2.0, (a[2]+b[2])/2.0]
def vec_lerp(a, b, t):
return [a[0] + t*(b[0]-a[0]), a[1] + t*(b[1]-a[1]), a[2] + t*(b[2]-a[2])]
def safe_sqrt(val):
if val < 0:
return 0.0
return math.sqrt(val)
def safe_div(num, denom, default=float('inf')):
if abs(denom) < 1e-12:
return default
return num / denom
class CircleProperties:
def __init__(self, radius, center_x=0.0, center_y=0.0):
self.shape_type = "Circle"
self.radius = abs(radius)
self.n = 0
r = self.radius
A = math.pi * r * r
I = math.pi * r**4 / 4.0
self.area = A
self.centroid_x = center_x
self.centroid_y = center_y
self.Ix_centroid = I
self.Iy_centroid = I
self.Ixy_centroid = 0.0
self.J_centroid = 2.0 * I
self.Ix_origin = I + A * center_y**2
self.Iy_origin = I + A * center_x**2
self.Ixy_origin = A * center_x * center_y
self.I_max = I
self.I_min = I
self.theta_principal = 0.0
self.theta_principal_deg = 0.0
self.rx = r / 2.0
self.ry = r / 2.0
self.rp = r / math.sqrt(2.0)
self.c_top = r
self.c_bottom = r
self.c_right = r
self.c_left = r
S = safe_div(I, r, 0.0)
self.Sx_top = S
self.Sx_bottom = S
self.Sy_right = S
self.Sy_left = S
self.Sx_min = S
self.Sy_min = S
class AnnulusProperties:
def __init__(self, outer_radius, inner_radius, center_x=0.0, center_y=0.0):
self.shape_type = "Annulus"
R = abs(outer_radius)
r = abs(inner_radius)
if R < r:
R, r = r, R
self.outer_radius = R
self.inner_radius = r
self.n = 0
A = math.pi * (R**2 - r**2)
I = math.pi * (R**4 - r**4) / 4.0
self.area = A
self.centroid_x = center_x
self.centroid_y = center_y
self.Ix_centroid = I
self.Iy_centroid = I
self.Ixy_centroid = 0.0
self.J_centroid = 2.0 * I
self.Ix_origin = I + A * center_y**2
self.Iy_origin = I + A * center_x**2
self.Ixy_origin = A * center_x * center_y
self.I_max = I
self.I_min = I
self.theta_principal = 0.0
self.theta_principal_deg = 0.0
self.rx = safe_sqrt(safe_div(I, A, 0.0))
self.ry = safe_sqrt(safe_div(I, A, 0.0))
self.rp = safe_sqrt(safe_div(2.0 * I, A, 0.0))
self.c_top = R
self.c_bottom = R
self.c_right = R
self.c_left = R
S = safe_div(I, R, 0.0)
self.Sx_top = S
self.Sx_bottom = S
self.Sy_right = S
self.Sy_left = S
self.Sx_min = S
self.Sy_min = S
class RectangleProperties:
def __init__(self, width, height, center_x=0.0, center_y=0.0, rotation=0.0):
self.shape_type = "Rectangle"
self.width = abs(width)
self.height = abs(height)
self.rotation = rotation
self.n = 4
b = self.width
h = self.height
A = b * h
Ix_local = b * h**3 / 12.0
Iy_local = b**3 * h / 12.0
self.area = A
self.centroid_x = center_x
self.centroid_y = center_y
cos2 = math.cos(2.0 * rotation)
sin2 = math.sin(2.0 * rotation)
I_avg = (Ix_local + Iy_local) / 2.0
I_diff = (Ix_local - Iy_local) / 2.0
self.Ix_centroid = I_avg + I_diff * cos2
self.Iy_centroid = I_avg - I_diff * cos2
self.Ixy_centroid = -I_diff * sin2
self.J_centroid = Ix_local + Iy_local
self.Ix_origin = self.Ix_centroid + A * center_y**2
self.Iy_origin = self.Iy_centroid + A * center_x**2
self.Ixy_origin = self.Ixy_centroid + A * center_x * center_y
self.I_max = max(Ix_local, Iy_local)
self.I_min = min(Ix_local, Iy_local)
self.theta_principal = rotation if Ix_local >= Iy_local else rotation + math.pi/2.0
self.theta_principal_deg = math.degrees(self.theta_principal)
self.rx = safe_sqrt(safe_div(self.Ix_centroid, A, 0.0))
self.ry = safe_sqrt(safe_div(self.Iy_centroid, A, 0.0))
self.rp = safe_sqrt(safe_div(self.J_centroid, A, 0.0))
cos_r = abs(math.cos(rotation))
sin_r = abs(math.sin(rotation))
self.c_top = (h * cos_r + b * sin_r) / 2.0
self.c_bottom = self.c_top
self.c_right = (b * cos_r + h * sin_r) / 2.0
self.c_left = self.c_right
self.Sx_top = safe_div(self.Ix_centroid, self.c_top)
self.Sx_bottom = self.Sx_top
self.Sy_right = safe_div(self.Iy_centroid, self.c_right)
self.Sy_left = self.Sy_right
self.Sx_min = self.Sx_top
self.Sy_min = self.Sy_right
class SemicircleProperties:
def __init__(self, radius, center_x=0.0, center_y=0.0, rotation=0.0):
self.shape_type = "Semicircle"
self.radius = abs(radius)
self.rotation = rotation
self.n = 0
r = self.radius
A = math.pi * r**2 / 2.0
y_bar = 4.0 * r / (3.0 * math.pi)
Ix_local = (math.pi/8.0 - 8.0/(9.0*math.pi)) * r**4
Iy_local = math.pi * r**4 / 8.0
self.area = A
cos_r = math.cos(rotation)
sin_r = math.sin(rotation)
self.centroid_x = center_x + y_bar * sin_r
self.centroid_y = center_y + y_bar * cos_r
cos2 = math.cos(2.0 * rotation)
sin2 = math.sin(2.0 * rotation)
I_avg = (Ix_local + Iy_local) / 2.0
I_diff = (Ix_local - Iy_local) / 2.0
self.Ix_centroid = I_avg + I_diff * cos2
self.Iy_centroid = I_avg - I_diff * cos2
self.Ixy_centroid = -I_diff * sin2
self.J_centroid = Ix_local + Iy_local
self.Ix_origin = self.Ix_centroid + A * self.centroid_y**2
self.Iy_origin = self.Iy_centroid + A * self.centroid_x**2
self.Ixy_origin = self.Ixy_centroid + A * self.centroid_x * self.centroid_y
self.I_max = max(Ix_local, Iy_local)
self.I_min = min(Ix_local, Iy_local)
self.theta_principal = rotation
self.theta_principal_deg = math.degrees(rotation)
self.rx = safe_sqrt(safe_div(self.Ix_centroid, A, 0.0))
self.ry = safe_sqrt(safe_div(self.Iy_centroid, A, 0.0))
self.rp = safe_sqrt(safe_div(self.J_centroid, A, 0.0))
self.c_top = r - y_bar
self.c_bottom = y_bar
self.c_right = r
self.c_left = r
self.Sx_top = safe_div(self.Ix_centroid, self.c_top)
self.Sx_bottom = safe_div(self.Ix_centroid, self.c_bottom)
self.Sy_right = safe_div(self.Iy_centroid, self.c_right)
self.Sy_left = safe_div(self.Iy_centroid, self.c_left)
self.Sx_min = min(self.Sx_top, self.Sx_bottom)
self.Sy_min = min(self.Sy_right, self.Sy_left)
class PolygonProperties:
def __init__(self, vertices_2d, shape_name="Polygon"):
self.shape_type = shape_name
self.vertices = vertices_2d
self.n = len(vertices_2d)
if self.n < 3:
raise ValueError("Polygon must have at least 3 vertices")
self._compute_all()
def _compute_all(self):
verts = self.vertices
n = self.n
signed_area = 0.0
for i in range(n):
j = (i + 1) % n
signed_area += verts[i][0] * verts[j][1]
signed_area -= verts[j][0] * verts[i][1]
signed_area *= 0.5
self.area = abs(signed_area)
if self.area < 1e-12:
raise ValueError("Polygon has zero or negligible area")
cx, cy = 0.0, 0.0
for i in range(n):
j = (i + 1) % n
cross = verts[i][0] * verts[j][1] - verts[j][0] * verts[i][1]
cx += (verts[i][0] + verts[j][0]) * cross
cy += (verts[i][1] + verts[j][1]) * cross
factor = 1.0 / (6.0 * signed_area) if abs(signed_area) > 1e-12 else 0.0
self.centroid_x = cx * factor
self.centroid_y = cy * factor
Ix, Iy, Ixy = 0.0, 0.0, 0.0
for i in range(n):
j = (i + 1) % n
x0, y0 = verts[i]
x1, y1 = verts[j]
cross = x0 * y1 - x1 * y0
Ix += (y0*y0 + y0*y1 + y1*y1) * cross
Iy += (x0*x0 + x0*x1 + x1*x1) * cross
Ixy += (x0*y1 + 2.0*x0*y0 + 2.0*x1*y1 + x1*y0) * cross
self.Ix_origin = abs(Ix / 12.0)
self.Iy_origin = abs(Iy / 12.0)
self.Ixy_origin = Ixy / 24.0 if signed_area > 0 else -Ixy / 24.0
A = self.area
self.Ix_centroid = abs(self.Ix_origin - A * self.centroid_y**2)
self.Iy_centroid = abs(self.Iy_origin - A * self.centroid_x**2)
self.Ixy_centroid = self.Ixy_origin - A * self.centroid_x * self.centroid_y
self.J_centroid = self.Ix_centroid + self.Iy_centroid
Ix_c, Iy_c, Ixy_c = self.Ix_centroid, self.Iy_centroid, self.Ixy_centroid
I_avg = (Ix_c + Iy_c) / 2.0
I_diff = (Ix_c - Iy_c) / 2.0
R = safe_sqrt(I_diff**2 + Ixy_c**2)
self.I_max = I_avg + R
self.I_min = max(0.0, I_avg - R)
if abs(Ixy_c) < 1e-12 and abs(I_diff) < 1e-12:
self.theta_principal = 0.0
else:
self.theta_principal = 0.5 * math.atan2(-2.0 * Ixy_c, Ix_c - Iy_c)
self.theta_principal_deg = math.degrees(self.theta_principal)
self.rx = safe_sqrt(safe_div(self.Ix_centroid, A, 0.0))
self.ry = safe_sqrt(safe_div(self.Iy_centroid, A, 0.0))
self.rp = safe_sqrt(safe_div(self.J_centroid, A, 0.0))
x_rel = [v[0] - self.centroid_x for v in verts]
y_rel = [v[1] - self.centroid_y for v in verts]
self.c_top = max(y_rel) if y_rel else 0.0
self.c_bottom = abs(min(y_rel)) if y_rel else 0.0
self.c_right = max(x_rel) if x_rel else 0.0
self.c_left = abs(min(x_rel)) if x_rel else 0.0
self.Sx_top = safe_div(self.Ix_centroid, self.c_top)
self.Sx_bottom = safe_div(self.Ix_centroid, self.c_bottom)
self.Sy_right = safe_div(self.Iy_centroid, self.c_right)
self.Sy_left = safe_div(self.Iy_centroid, self.c_left)
self.Sx_min = min(self.Sx_top, self.Sx_bottom)
self.Sy_min = min(self.Sy_right, self.Sy_left)
class PolygonWithCircularHoleProperties:
def __init__(self, outer_vertices_2d, hole_radius, hole_center_x=None, hole_center_y=None, shape_name="Polygon with Hole"):
self.shape_type = shape_name
outer = PolygonProperties(outer_vertices_2d, "outer")
if hole_center_x is None:
hole_center_x = outer.centroid_x
if hole_center_y is None:
hole_center_y = outer.centroid_y
r = abs(hole_radius)
hole_area = math.pi * r * r
hole_Ic = math.pi * r**4 / 4.0
dx = hole_center_x - outer.centroid_x
dy = hole_center_y - outer.centroid_y
hole_Ix_at_centroid = hole_Ic + hole_area * dy**2
hole_Iy_at_centroid = hole_Ic + hole_area * dx**2
hole_Ixy_at_centroid = hole_area * dx * dy
self.n = outer.n
self.area = outer.area - hole_area
if self.area < 1e-12:
raise ValueError("Hole area exceeds outer polygon area")
self.centroid_x = outer.centroid_x
self.centroid_y = outer.centroid_y
self.Ix_centroid = outer.Ix_centroid - hole_Ix_at_centroid
self.Iy_centroid = outer.Iy_centroid - hole_Iy_at_centroid
self.Ixy_centroid = outer.Ixy_centroid - hole_Ixy_at_centroid
self.J_centroid = self.Ix_centroid + self.Iy_centroid
self.Ix_origin = outer.Ix_origin - (hole_Ic + hole_area * hole_center_y**2)
self.Iy_origin = outer.Iy_origin - (hole_Ic + hole_area * hole_center_x**2)
self.Ixy_origin = outer.Ixy_origin - hole_area * hole_center_x * hole_center_y
Ix_c, Iy_c, Ixy_c = self.Ix_centroid, self.Iy_centroid, self.Ixy_centroid
I_avg = (Ix_c + Iy_c) / 2.0
I_diff = (Ix_c - Iy_c) / 2.0
R = safe_sqrt(I_diff**2 + Ixy_c**2)
self.I_max = I_avg + R
self.I_min = max(0.0, I_avg - R)
if abs(Ixy_c) < 1e-12 and abs(I_diff) < 1e-12:
self.theta_principal = 0.0
else:
self.theta_principal = 0.5 * math.atan2(-2.0 * Ixy_c, Ix_c - Iy_c)
self.theta_principal_deg = math.degrees(self.theta_principal)
self.rx = safe_sqrt(safe_div(self.Ix_centroid, self.area, 0.0))
self.ry = safe_sqrt(safe_div(self.Iy_centroid, self.area, 0.0))
self.rp = safe_sqrt(safe_div(self.J_centroid, self.area, 0.0))
self.c_top = outer.c_top
self.c_bottom = outer.c_bottom
self.c_right = outer.c_right
self.c_left = outer.c_left
self.Sx_top = safe_div(self.Ix_centroid, self.c_top)
self.Sx_bottom = safe_div(self.Ix_centroid, self.c_bottom)
self.Sy_right = safe_div(self.Iy_centroid, self.c_right)
self.Sy_left = safe_div(self.Iy_centroid, self.c_left)
self.Sx_min = min(self.Sx_top, self.Sx_bottom)
self.Sy_min = min(self.Sy_right, self.Sy_left)
self.outer_area = outer.area
self.hole_radius = r
self.hole_area = hole_area
x_coords = [v[0] for v in outer_vertices_2d]
y_coords = [v[1] for v in outer_vertices_2d]
self.outer_width = max(x_coords) - min(x_coords)
self.outer_height = max(y_coords) - min(y_coords)
class EdgeInfo:
def __init__(self, edge, index):
self.edge = edge
self.index = index
self.diameter = None
self.length = None
self.vertices = []
self.vertex_count = 0
self.is_circular = False
self.is_closed = False
self.is_full_circle = False
self.is_curved = False
self.chord_length = 0.0
self._analyze()
def _analyze(self):
try:
d = self.edge.Diameter
if d is not None and d > 0:
self.diameter = d
self.is_circular = True
except Exception:
pass
try:
self.length = self.edge.Length
except Exception:
pass
try:
verts = self.edge.GetVertices()
if verts:
self.vertex_count = len(verts)
for v in verts:
self.vertices.append([v.X, v.Y, v.Z])
except Exception:
pass
self.is_closed = (self.vertex_count == 0)
if self.is_circular and self.diameter:
if self.is_closed:
self.is_full_circle = True
elif not self.length or self.length < 1e-9:
self.is_full_circle = True
elif self.length > 0:
expected_circumference = math.pi * self.diameter
if abs(self.length - expected_circumference) < expected_circumference * CIRCUMFERENCE_TOLERANCE:
self.is_full_circle = True
if self.vertex_count >= 2:
self.chord_length = vec_distance(self.vertices[0], self.vertices[1])
if self.length and self.chord_length > 1e-12:
ratio = self.length / self.chord_length
if ratio > CURVATURE_THRESHOLD:
self.is_curved = True
def is_complete_circle(edge_info):
return edge_info.is_closed or edge_info.is_full_circle
def collect_unique_vertices(edges, tolerance=VERTEX_TOLERANCE):
all_verts = []
for e in edges:
for v in e.vertices:
is_dup = False
for existing in all_verts:
if vec_distance(v, existing) < tolerance:
is_dup = True
break
if not is_dup:
all_verts.append(v)
return all_verts
def analyze_face_geometry(face, num_segments=CURVE_SEGMENTS):
alibre_area = None
try:
alibre_area = face.GetArea()
if alibre_area == 0:
alibre_area = None
except Exception:
pass
edges = []
try:
edges = face.GetEdges() or []
except Exception:
pass
face_vertices = []
try:
face_vertices = face.GetVertices() or []
except Exception:
pass
is_rect = False
try:
is_rect = face.IsRectangle()
except Exception:
pass
edge_infos = [EdgeInfo(e, i) for i, e in enumerate(edges)]
circular_edges = [e for e in edge_infos if e.is_circular]
curved_edges = [e for e in edge_infos if e.is_curved and not e.is_circular]
linear_edges = [e for e in edge_infos if not e.is_curved and not e.is_circular and e.vertex_count >= 2]
diameters = [e.diameter for e in circular_edges if e.diameter]
unique_diameters = list(set([round(d, 6) for d in diameters]))
if is_rect and len(linear_edges) == 4:
lengths = sorted([e.length for e in linear_edges if e.length])
if len(lengths) == 4:
width = (lengths[0] + lengths[1]) / 2.0
height = (lengths[2] + lengths[3]) / 2.0
return ("rectangle", RectangleProperties(width, height), alibre_area)
if len(circular_edges) == 1 and is_complete_circle(circular_edges[0]) and len(linear_edges) == 0:
radius = circular_edges[0].diameter / 2.0
return ("circle", CircleProperties(radius), alibre_area)
if len(circular_edges) == 2 and all(is_complete_circle(e) for e in circular_edges):
r1 = circular_edges[0].diameter / 2.0
r2 = circular_edges[1].diameter / 2.0
outer_r, inner_r = max(r1, r2), min(r1, r2)
if outer_r - inner_r < 0.001:
return ("circle", CircleProperties(outer_r), alibre_area)
return ("annulus", AnnulusProperties(outer_r, inner_r), alibre_area)
if len(unique_diameters) == 1 and len(circular_edges) >= 1 and len(linear_edges) == 0:
radius = unique_diameters[0] / 2.0
total_arc = sum(e.length for e in circular_edges if e.length)
expected_circumference = math.pi * unique_diameters[0]
if abs(total_arc - expected_circumference) < expected_circumference * 0.02:
return ("circle", CircleProperties(radius), alibre_area)
if len(unique_diameters) == 2:
r1, r2 = max(unique_diameters) / 2.0, min(unique_diameters) / 2.0
if r1 - r2 < 0.001:
return ("circle", CircleProperties(r1), alibre_area)
return ("annulus", AnnulusProperties(r1, r2), alibre_area)
if len(circular_edges) == 1 and len(linear_edges) == 1:
arc_edge = circular_edges[0]
if arc_edge.diameter and arc_edge.length:
expected_semicircle = math.pi * arc_edge.diameter / 2.0
if abs(arc_edge.length - expected_semicircle) < expected_semicircle * ARC_LENGTH_TOLERANCE:
radius = arc_edge.diameter / 2.0
return ("semicircle", SemicircleProperties(radius), alibre_area)
if len(linear_edges) >= 3 and len(circular_edges) == 1 and is_complete_circle(circular_edges[0]):
hole_edge = circular_edges[0]
if hole_edge.diameter:
hole_radius = hole_edge.diameter / 2.0
outer_verts = collect_unique_vertices(linear_edges)
if len(outer_verts) >= 3:
outer_2d = project_to_2d(outer_verts)
shape_name = "Polygon (%d sides) with Hole" % len(linear_edges)
return ("polygon_with_hole", PolygonWithCircularHoleProperties(outer_2d, hole_radius, shape_name=shape_name), alibre_area)
if len(linear_edges) == 3 and len(circular_edges) == 0:
all_verts = collect_unique_vertices(linear_edges)
if len(all_verts) == 3:
points_2d = project_to_2d(all_verts)
return ("triangle", PolygonProperties(points_2d, "Triangle"), alibre_area)
if len(linear_edges) >= 3 and len(circular_edges) == 0 and len(curved_edges) == 0:
all_verts = collect_unique_vertices(linear_edges)
if len(all_verts) >= 3:
points_2d = project_to_2d(all_verts)
return ("polygon", PolygonProperties(points_2d, "Polygon (%d sides)" % len(linear_edges)), alibre_area)
if len(curved_edges) > 0 or (len(circular_edges) > 0 and not all(is_complete_circle(e) for e in circular_edges)):
boundary_points = discretize_face_boundary(edge_infos, num_segments)
if len(boundary_points) >= 3:
points_2d = project_to_2d(boundary_points)
return ("freeform", PolygonProperties(points_2d, "Freeform (%d pts)" % len(points_2d)), alibre_area)
boundary_points = []
for v in face_vertices:
try:
pt = [v.X, v.Y, v.Z]
is_dup = any(vec_distance(pt, ex) < VERTEX_TOLERANCE for ex in boundary_points)
if not is_dup:
boundary_points.append(pt)
except Exception:
pass
if len(boundary_points) >= 3:
points_2d = project_to_2d(boundary_points)
return ("polygon", PolygonProperties(points_2d, "Polygon (from vertices)"), alibre_area)
if alibre_area and alibre_area > 0:
radius = math.sqrt(alibre_area / math.pi)
props = CircleProperties(radius)
props.shape_type = "Equivalent Circle (from area)"
return ("equivalent_circle", props, alibre_area)
return ("unknown", None, alibre_area)
def discretize_face_boundary(edge_infos, num_segments):
boundary_points = []
ordered_edges = order_edges_by_connectivity(edge_infos)
for edge_info in ordered_edges:
if is_complete_circle(edge_info) and edge_info.diameter:
radius = edge_info.diameter / 2.0
center = estimate_circle_center(edge_info)
for i in range(num_segments):
angle = 2.0 * math.pi * i / num_segments
pt = [center[0] + radius * math.cos(angle), center[1] + radius * math.sin(angle), center[2]]
boundary_points.append(pt)
elif edge_info.is_curved or edge_info.is_circular:
pts = discretize_curved_edge(edge_info, max(8, num_segments // 4))
for pt in pts:
is_dup = any(vec_distance(pt, ex) < VERTEX_TOLERANCE for ex in boundary_points)
if not is_dup:
boundary_points.append(pt)
else:
for v in edge_info.vertices:
is_dup = any(vec_distance(v, ex) < VERTEX_TOLERANCE for ex in boundary_points)
if not is_dup:
boundary_points.append(v)
return boundary_points
def order_edges_by_connectivity(edge_infos):
if not edge_infos:
return []
ordered = []
remaining = list(edge_infos)
ordered.append(remaining.pop(0))
while remaining:
last_edge = ordered[-1]
found_idx = -1
for i, edge in enumerate(remaining):
if edges_share_vertex(last_edge, edge):
found_idx = i
break
if found_idx >= 0:
ordered.append(remaining.pop(found_idx))
else:
ordered.append(remaining.pop(0))
return ordered
def edges_share_vertex(edge1, edge2):
for v1 in edge1.vertices:
for v2 in edge2.vertices:
if vec_distance(v1, v2) < VERTEX_TOLERANCE:
return True
return False
def estimate_circle_center(edge_info):
if edge_info.vertices:
n = len(edge_info.vertices)
cx = sum(v[0] for v in edge_info.vertices) / n
cy = sum(v[1] for v in edge_info.vertices) / n
cz = sum(v[2] for v in edge_info.vertices) / n
return [cx, cy, cz]
return [0.0, 0.0, 0.0]
def discretize_curved_edge(edge_info, num_points):
points = []
num_points = max(4, num_points)
if len(edge_info.vertices) >= 2:
v1, v2 = edge_info.vertices[0], edge_info.vertices[1]
for i in range(num_points + 1):
t = i / float(num_points)
points.append(vec_lerp(v1, v2, t))
return points
def project_to_2d(points_3d):
n = len(points_3d)
if n < 3:
raise ValueError("Need at least 3 points for 2D projection")
cx = sum(p[0] for p in points_3d) / n
cy = sum(p[1] for p in points_3d) / n
cz = sum(p[2] for p in points_3d) / n
origin = [cx, cy, cz]
p0 = points_3d[0]
v1 = None
for i in range(1, n):
vec = vec_subtract(points_3d[i], p0)
if vec_length(vec) > VERTEX_TOLERANCE:
v1 = vec
break
if v1 is None:
raise ValueError("All points are coincident")
v2 = None
for i in range(2, n):
vec = vec_subtract(points_3d[i], p0)
cross = vec_cross(v1, vec)
if vec_length(cross) > VERTEX_TOLERANCE:
v2 = vec
break
if v2 is None:
if abs(v1[2]) < 0.9:
v2 = vec_cross(v1, [0.0, 0.0, 1.0])
else:
v2 = vec_cross(v1, [1.0, 0.0, 0.0])
normal = vec_normalize(vec_cross(v1, v2))
u_axis = vec_normalize(v1)
v_axis = vec_cross(normal, u_axis)
points_2d = []
for p3d in points_3d:
rel = vec_subtract(p3d, origin)
u = vec_dot(rel, u_axis)
v = vec_dot(rel, v_axis)
points_2d.append([u, v])
cx2 = sum(p[0] for p in points_2d) / n
cy2 = sum(p[1] for p in points_2d) / n
def angle_key(p):
return math.atan2(p[1] - cy2, p[0] - cx2)
points_2d.sort(key=angle_key)
return points_2d
def fmt(value, decimals=6):
if value is None:
return "N/A"
if isinstance(value, float) and (math.isinf(value) or math.isnan(value)):
return "N/A"
if abs(value) < 1e-10:
return "0.0"
elif abs(value) >= 1e6 or (abs(value) < 0.001 and abs(value) > 1e-10):
return "%.4e" % value
else:
return ("%%.%df" % decimals) % value
UNIT_CONVERSIONS = {
'mm': 1.0,
'cm': 0.1,
'm': 0.001,
'in': 1.0 / 25.4,
'ft': 1.0 / 304.8
}
def convert_value(value, power, unit):
if value is None or (isinstance(value, float) and (math.isinf(value) or math.isnan(value))):
return value
factor = UNIT_CONVERSIONS[unit] ** power
return value * factor
def generate_face_section(face_name, props, alibre_area, unit):
u1 = unit
u2 = unit + "^2"
u3 = unit + "^3"
u4 = unit + "^4"
p = props
lines = []
lines.append(" %s (%s)" % (face_name, props.shape_type))
lines.append(" " + "-" * 40)
if hasattr(props, 'radius') and not hasattr(props, 'outer_radius'):
lines.append(" Radius: %s %s" % (fmt(convert_value(props.radius, 1, unit)), u1))
if hasattr(props, 'outer_radius'):
lines.append(" Outer R: %s %s" % (fmt(convert_value(props.outer_radius, 1, unit)), u1))
lines.append(" Inner R: %s %s" % (fmt(convert_value(props.inner_radius, 1, unit)), u1))
if hasattr(props, 'width') and hasattr(props, 'height'):
lines.append(" Width: %s %s" % (fmt(convert_value(props.width, 1, unit)), u1))
lines.append(" Height: %s %s" % (fmt(convert_value(props.height, 1, unit)), u1))
if hasattr(props, 'outer_width') and hasattr(props, 'outer_height'):
lines.append(" Outer W: %s %s" % (fmt(convert_value(props.outer_width, 1, unit)), u1))
lines.append(" Outer H: %s %s" % (fmt(convert_value(props.outer_height, 1, unit)), u1))
if hasattr(props, 'hole_radius'):
lines.append(" Hole R: %s %s" % (fmt(convert_value(props.hole_radius, 1, unit)), u1))
lines.append(" Area: %s %s" % (fmt(convert_value(p.area, 2, unit)), u2))
lines.append(" Ix-x: %s %s" % (fmt(convert_value(p.Ix_centroid, 4, unit)), u4))
lines.append(" Iy-y: %s %s" % (fmt(convert_value(p.Iy_centroid, 4, unit)), u4))
lines.append(" J: %s %s" % (fmt(convert_value(p.J_centroid, 4, unit)), u4))
lines.append(" rx-x: %s %s" % (fmt(convert_value(p.rx, 1, unit)), u1))
lines.append(" ry-y: %s %s" % (fmt(convert_value(p.ry, 1, unit)), u1))
lines.append(" Sx-x (min): %s %s" % (fmt(convert_value(p.Sx_min, 3, unit)), u3))
lines.append(" Sy-y (min): %s %s" % (fmt(convert_value(p.Sy_min, 3, unit)), u3))
lines.append("")
return "\n".join(lines)
def generate_batch_report(face_results):
lines = []
lines.append("")
lines.append("=" * 70)
lines.append(" BATCH AREA MOMENTS REPORT")
lines.append(" %s v%s" % (ScriptName, ScriptVersion))
lines.append("=" * 70)
lines.append("")
lines.append("Faces Analyzed: %d" % len(face_results))
lines.append("")
for unit in ['mm', 'cm', 'm', 'in', 'ft']:
lines.append("=" * 70)
lines.append("RESULTS IN %s" % unit.upper())
lines.append("=" * 70)
lines.append("")
for face_name, props, alibre_area in face_results:
if props is not None:
lines.append(generate_face_section(face_name, props, alibre_area, unit))
lines.append("=" * 70)
lines.append("END OF REPORT")
lines.append("=" * 70)
return "\n".join(lines)
def get_all_faces(part):
faces = []
try:
all_faces = part.GetFaces()
if all_faces:
for face in all_faces:
try:
name = face.Name if hasattr(face, 'Name') and face.Name else None
if name:
faces.append((name, face))
except Exception:
pass
except Exception:
pass
faces.sort(key=lambda x: x[0])
return faces
def run():
Win = Windows()
try:
part = CurrentPart()
if part is None:
Win.ErrorDialog("Please open a part before running this script.", ScriptName)
return
except Exception:
Win.ErrorDialog("Please open a part before running this script.", ScriptName)
return
all_faces = get_all_faces(part)
if not all_faces:
Win.ErrorDialog("No named faces found in the part.\n\nFaces should be named like Face<1>, Face<2>, etc.", ScriptName)
return
print "=" * 70
print "BATCH AREA MOMENTS - Scanning %d faces..." % len(all_faces)
print "=" * 70
face_results = []
for face_name, face in all_faces:
print "Analyzing: %s" % face_name
try:
shape_type, props, alibre_area = analyze_face_geometry(face, CURVE_SEGMENTS)
if props is not None:
if shape_type not in ("polygon_with_hole", "circle", "annulus", "rectangle"):
if alibre_area and alibre_area > 0 and props.area > 0:
area_ratio = alibre_area / props.area
if area_ratio > 1.10 or area_ratio < 0.90:
print " -> Skipping (non-planar, area mismatch: %.1f%%)" % ((area_ratio - 1.0) * 100)
continue
face_results.append((face_name, props, alibre_area))
print " -> %s (Area: %.2f mm^2)" % (props.shape_type, props.area)
else:
print " -> Could not determine geometry"
except Exception as ex:
print " -> Error: %s" % str(ex)
print ""
if not face_results:
Win.ErrorDialog("No faces could be analyzed.\n\nMake sure faces are planar.", ScriptName)
return
report = generate_batch_report(face_results)
print report
sys.stdout.flush()
Win.InfoDialog("Batch analysis complete!\n\n%d faces analyzed.\nSee console for full report." % len(face_results), ScriptName)
run()
Topology Summary:
Type Total Failed
------------ ----- ------
Bodies 1 0
Faces 10 0
Edges 16 0
Vertices 12 0
Lumps 1 -
Shells 1 -
Loops 14 -
Coedges 32 -
TEdges 0 -
TVertices 0 -
TCoedges 0 -
======================================================================
BATCH AREA MOMENTS - Scanning 10 faces...
======================================================================
Analyzing: Face<10>
-> Polygon (4 sides) (Area: 13664.78 mm^2)
Analyzing: Face<1>
-> Annulus (Area: 335.64 mm^2)
Analyzing: Face<2>
-> Circle (Area: 1140.09 mm^2)
Analyzing: Face<3>
-> Circle (Area: 804.45 mm^2)
Analyzing: Face<4>
-> Annulus (Area: 2026.83 mm^2)
Analyzing: Face<5>
-> Polygon (4 sides) with Hole (Area: 2639.52 mm^2)
Analyzing: Face<6>
-> Rectangle (Area: 47096.73 mm^2)
Analyzing: Face<7>
-> Polygon (4 sides) (Area: 13643.50 mm^2)
Analyzing: Face<8>
-> Polygon (4 sides) (Area: 13664.78 mm^2)
Analyzing: Face<9>
-> Polygon (4 sides) (Area: 13643.50 mm^2)
======================================================================
BATCH AREA MOMENTS REPORT
Batch Area Moments v1.0
======================================================================
Faces Analyzed: 10
======================================================================
RESULTS IN MM
======================================================================
Face<10> (Polygon (4 sides))
----------------------------------------
Area: 13664.781537 mm^2
Ix-x: 9.2139e+06 mm^4
Iy-y: 2.9826e+07 mm^4
J: 3.9040e+07 mm^4
rx-x: 25.966873 mm
ry-y: 46.719223 mm
Sx-x (min): 169835.357191 mm^3
Sy-y (min): 276397.051143 mm^3
Face<1> (Annulus)
----------------------------------------
Outer R: 19.050000 mm
Inner R: 16.002000 mm
Area: 335.643034 mm^2
Ix-x: 51937.948861 mm^4
Iy-y: 51937.948861 mm^4
J: 103875.897721 mm^4
rx-x: 12.439519 mm
ry-y: 12.439519 mm
Sx-x (min): 2726.401515 mm^3
Sy-y (min): 2726.401515 mm^3
Face<2> (Circle)
----------------------------------------
Radius: 19.050000 mm
Area: 1140.091828 mm^2
Ix-x: 103435.543650 mm^4
Iy-y: 103435.543650 mm^4
J: 206871.087300 mm^4
rx-x: 9.525000 mm
ry-y: 9.525000 mm
Sx-x (min): 5429.687331 mm^3
Sy-y (min): 5429.687331 mm^3
Face<3> (Circle)
----------------------------------------
Radius: 16.002000 mm
Area: 804.448794 mm^2
Ix-x: 51497.594789 mm^4
Iy-y: 51497.594789 mm^4
J: 102995.189579 mm^4
rx-x: 8.001000 mm
ry-y: 8.001000 mm
Sx-x (min): 3218.197400 mm^3
Sy-y (min): 3218.197400 mm^3
Face<4> (Annulus)
----------------------------------------
Outer R: 31.750000 mm
Inner R: 19.050000 mm
Area: 2026.829916 mm^2
Ix-x: 694678.219081 mm^4
Iy-y: 694678.219081 mm^4
J: 1.3894e+06 mm^4
rx-x: 18.513272 mm
ry-y: 18.513272 mm
Sx-x (min): 21879.628947 mm^3
Sy-y (min): 21879.628947 mm^3
Face<5> (Polygon (4 sides) with Hole)
----------------------------------------
Outer W: 76.200000 mm
Outer H: 76.200000 mm
Hole R: 31.750000 mm
Area: 2639.518256 mm^2
Ix-x: 2.0114e+06 mm^4
Iy-y: 2.0114e+06 mm^4
J: 4.0229e+06 mm^4
rx-x: 27.605277 mm
ry-y: 27.605277 mm
Sx-x (min): 52793.920212 mm^3
Sy-y (min): 52793.920212 mm^3
Face<6> (Rectangle)
----------------------------------------
Width: 215.819414 mm
Height: 218.222875 mm
Area: 47096.733130 mm^2
Ix-x: 1.8690e+08 mm^4
Iy-y: 1.8281e+08 mm^4
J: 3.6971e+08 mm^4
rx-x: 62.995518 mm
ry-y: 62.301698 mm
Sx-x (min): 1.7129e+06 mm^3
Sy-y (min): 1.6941e+06 mm^3
Face<7> (Polygon (4 sides))
----------------------------------------
Area: 13643.503951 mm^2
Ix-x: 9.0085e+06 mm^4
Iy-y: 3.0373e+07 mm^4
J: 3.9381e+07 mm^4
rx-x: 25.695803 mm
ry-y: 47.182122 mm
Sx-x (min): 167471.687718 mm^3
Sy-y (min): 278362.405971 mm^3
Face<8> (Polygon (4 sides))
----------------------------------------
Area: 13664.781537 mm^2
Ix-x: 9.2139e+06 mm^4
Iy-y: 2.9826e+07 mm^4
J: 3.9040e+07 mm^4
rx-x: 25.966873 mm
ry-y: 46.719223 mm
Sx-x (min): 169835.357191 mm^3
Sy-y (min): 276397.051143 mm^3
Face<9> (Polygon (4 sides))
----------------------------------------
Area: 13643.503951 mm^2
Ix-x: 9.0085e+06 mm^4
Iy-y: 3.0373e+07 mm^4
J: 3.9381e+07 mm^4
rx-x: 25.695803 mm
ry-y: 47.182122 mm
Sx-x (min): 167471.687718 mm^3
Sy-y (min): 278362.405971 mm^3
======================================================================
RESULTS IN CM
======================================================================
Face<10> (Polygon (4 sides))
----------------------------------------
Area: 136.647815 cm^2
Ix-x: 921.386819 cm^4
Iy-y: 2982.592485 cm^4
J: 3903.979304 cm^4
rx-x: 2.596687 cm
ry-y: 4.671922 cm
Sx-x (min): 169.835357 cm^3
Sy-y (min): 276.397051 cm^3
Face<1> (Annulus)
----------------------------------------
Outer R: 1.905000 cm
Inner R: 1.600200 cm
Area: 3.356430 cm^2
Ix-x: 5.193795 cm^4
Iy-y: 5.193795 cm^4
J: 10.387590 cm^4
rx-x: 1.243952 cm
ry-y: 1.243952 cm
Sx-x (min): 2.726402 cm^3
Sy-y (min): 2.726402 cm^3
Face<2> (Circle)
----------------------------------------
Radius: 1.905000 cm
Area: 11.400918 cm^2
Ix-x: 10.343554 cm^4
Iy-y: 10.343554 cm^4
J: 20.687109 cm^4
rx-x: 0.952500 cm
ry-y: 0.952500 cm
Sx-x (min): 5.429687 cm^3
Sy-y (min): 5.429687 cm^3
Face<3> (Circle)
----------------------------------------
Radius: 1.600200 cm
Area: 8.044488 cm^2
Ix-x: 5.149759 cm^4
Iy-y: 5.149759 cm^4
J: 10.299519 cm^4
rx-x: 0.800100 cm
ry-y: 0.800100 cm
Sx-x (min): 3.218197 cm^3
Sy-y (min): 3.218197 cm^3
Face<4> (Annulus)
----------------------------------------
Outer R: 3.175000 cm
Inner R: 1.905000 cm
Area: 20.268299 cm^2
Ix-x: 69.467822 cm^4
Iy-y: 69.467822 cm^4
J: 138.935644 cm^4
rx-x: 1.851327 cm
ry-y: 1.851327 cm
Sx-x (min): 21.879629 cm^3
Sy-y (min): 21.879629 cm^3
Face<5> (Polygon (4 sides) with Hole)
----------------------------------------
Outer W: 7.620000 cm
Outer H: 7.620000 cm
Hole R: 3.175000 cm
Area: 26.395183 cm^2
Ix-x: 201.144836 cm^4
Iy-y: 201.144836 cm^4
J: 402.289672 cm^4
rx-x: 2.760528 cm
ry-y: 2.760528 cm
Sx-x (min): 52.793920 cm^3
Sy-y (min): 52.793920 cm^3
Face<6> (Rectangle)
----------------------------------------
Width: 21.581941 cm
Height: 21.822288 cm
Area: 470.967331 cm^2
Ix-x: 18690.033702 cm^4
Iy-y: 18280.604657 cm^4
J: 36970.638359 cm^4
rx-x: 6.299552 cm
ry-y: 6.230170 cm
Sx-x (min): 1712.930753 cm^3
Sy-y (min): 1694.064893 cm^3
Face<7> (Polygon (4 sides))
----------------------------------------
Area: 136.435040 cm^2
Ix-x: 900.845517 cm^4
Iy-y: 3037.252230 cm^4
J: 3938.097746 cm^4
rx-x: 2.569580 cm
ry-y: 4.718212 cm
Sx-x (min): 167.471688 cm^3
Sy-y (min): 278.362406 cm^3
Face<8> (Polygon (4 sides))
----------------------------------------
Area: 136.647815 cm^2
Ix-x: 921.386819 cm^4
Iy-y: 2982.592485 cm^4
J: 3903.979304 cm^4
rx-x: 2.596687 cm
ry-y: 4.671922 cm
Sx-x (min): 169.835357 cm^3
Sy-y (min): 276.397051 cm^3
Face<9> (Polygon (4 sides))
----------------------------------------
Area: 136.435040 cm^2
Ix-x: 900.845517 cm^4
Iy-y: 3037.252230 cm^4
J: 3938.097746 cm^4
rx-x: 2.569580 cm
ry-y: 4.718212 cm
Sx-x (min): 167.471688 cm^3
Sy-y (min): 278.362406 cm^3
======================================================================
RESULTS IN M
======================================================================
Face<10> (Polygon (4 sides))
----------------------------------------
Area: 0.013665 m^2
Ix-x: 9.2139e-06 m^4
Iy-y: 2.9826e-05 m^4
J: 3.9040e-05 m^4
rx-x: 0.025967 m
ry-y: 0.046719 m
Sx-x (min): 1.6984e-04 m^3
Sy-y (min): 2.7640e-04 m^3
Face<1> (Annulus)
----------------------------------------
Outer R: 0.019050 m
Inner R: 0.016002 m
Area: 3.3564e-04 m^2
Ix-x: 5.1938e-08 m^4
Iy-y: 5.1938e-08 m^4
J: 1.0388e-07 m^4
rx-x: 0.012440 m
ry-y: 0.012440 m
Sx-x (min): 2.7264e-06 m^3
Sy-y (min): 2.7264e-06 m^3
Face<2> (Circle)
----------------------------------------
Radius: 0.019050 m
Area: 0.001140 m^2
Ix-x: 1.0344e-07 m^4
Iy-y: 1.0344e-07 m^4
J: 2.0687e-07 m^4
rx-x: 0.009525 m
ry-y: 0.009525 m
Sx-x (min): 5.4297e-06 m^3
Sy-y (min): 5.4297e-06 m^3
Face<3> (Circle)
----------------------------------------
Radius: 0.016002 m
Area: 8.0445e-04 m^2
Ix-x: 5.1498e-08 m^4
Iy-y: 5.1498e-08 m^4
J: 1.0300e-07 m^4
rx-x: 0.008001 m
ry-y: 0.008001 m
Sx-x (min): 3.2182e-06 m^3
Sy-y (min): 3.2182e-06 m^3
Face<4> (Annulus)
----------------------------------------
Outer R: 0.031750 m
Inner R: 0.019050 m
Area: 0.002027 m^2
Ix-x: 6.9468e-07 m^4
Iy-y: 6.9468e-07 m^4
J: 1.3894e-06 m^4
rx-x: 0.018513 m
ry-y: 0.018513 m
Sx-x (min): 2.1880e-05 m^3
Sy-y (min): 2.1880e-05 m^3
Face<5> (Polygon (4 sides) with Hole)
----------------------------------------
Outer W: 0.076200 m
Outer H: 0.076200 m
Hole R: 0.031750 m
Area: 0.002640 m^2
Ix-x: 2.0114e-06 m^4
Iy-y: 2.0114e-06 m^4
J: 4.0229e-06 m^4
rx-x: 0.027605 m
ry-y: 0.027605 m
Sx-x (min): 5.2794e-05 m^3
Sy-y (min): 5.2794e-05 m^3
Face<6> (Rectangle)
----------------------------------------
Width: 0.215819 m
Height: 0.218223 m
Area: 0.047097 m^2
Ix-x: 1.8690e-04 m^4
Iy-y: 1.8281e-04 m^4
J: 3.6971e-04 m^4
rx-x: 0.062996 m
ry-y: 0.062302 m
Sx-x (min): 0.001713 m^3
Sy-y (min): 0.001694 m^3
Face<7> (Polygon (4 sides))
----------------------------------------
Area: 0.013644 m^2
Ix-x: 9.0085e-06 m^4
Iy-y: 3.0373e-05 m^4
J: 3.9381e-05 m^4
rx-x: 0.025696 m
ry-y: 0.047182 m
Sx-x (min): 1.6747e-04 m^3
Sy-y (min): 2.7836e-04 m^3
Face<8> (Polygon (4 sides))
----------------------------------------
Area: 0.013665 m^2
Ix-x: 9.2139e-06 m^4
Iy-y: 2.9826e-05 m^4
J: 3.9040e-05 m^4
rx-x: 0.025967 m
ry-y: 0.046719 m
Sx-x (min): 1.6984e-04 m^3
Sy-y (min): 2.7640e-04 m^3
Face<9> (Polygon (4 sides))
----------------------------------------
Area: 0.013644 m^2
Ix-x: 9.0085e-06 m^4
Iy-y: 3.0373e-05 m^4
J: 3.9381e-05 m^4
rx-x: 0.025696 m
ry-y: 0.047182 m
Sx-x (min): 1.6747e-04 m^3
Sy-y (min): 2.7836e-04 m^3
======================================================================
RESULTS IN IN
======================================================================
Face<10> (Polygon (4 sides))
----------------------------------------
Area: 21.180454 in^2
Ix-x: 22.136407 in^4
Iy-y: 71.657071 in^4
J: 93.793478 in^4
rx-x: 1.022318 in
ry-y: 1.839339 in
Sx-x (min): 10.363989 in^3
Sy-y (min): 16.866783 in^3
Face<1> (Annulus)
----------------------------------------
Outer R: 0.750000 in
Inner R: 0.630000 in
Area: 0.520248 in^2
Ix-x: 0.124781 in^4
Iy-y: 0.124781 in^4
J: 0.249563 in^4
rx-x: 0.489745 in
ry-y: 0.489745 in
Sx-x (min): 0.166375 in^3
Sy-y (min): 0.166375 in^3
Face<2> (Circle)
----------------------------------------
Radius: 0.750000 in
Area: 1.767146 in^2
Ix-x: 0.248505 in^4
Iy-y: 0.248505 in^4
J: 0.497010 in^4
rx-x: 0.375000 in
ry-y: 0.375000 in
Sx-x (min): 0.331340 in^3
Sy-y (min): 0.331340 in^3
Face<3> (Circle)
----------------------------------------
Radius: 0.630000 in
Area: 1.246898 in^2
Ix-x: 0.123723 in^4
Iy-y: 0.123723 in^4
J: 0.247447 in^4
rx-x: 0.315000 in
ry-y: 0.315000 in
Sx-x (min): 0.196386 in^3
Sy-y (min): 0.196386 in^3
Face<4> (Annulus)
----------------------------------------
Outer R: 1.250000 in
Inner R: 0.750000 in
Area: 3.141593 in^2
Ix-x: 1.668971 in^4
Iy-y: 1.668971 in^4
J: 3.337942 in^4
rx-x: 0.728869 in
ry-y: 0.728869 in
Sx-x (min): 1.335177 in^3
Sy-y (min): 1.335177 in^3
Face<5> (Polygon (4 sides) with Hole)
----------------------------------------
Outer W: 3.000000 in
Outer H: 3.000000 in
Hole R: 1.250000 in
Area: 4.091261 in^2
Ix-x: 4.832524 in^4
Iy-y: 4.832524 in^4
J: 9.665048 in^4
rx-x: 1.086822 in
ry-y: 1.086822 in
Sx-x (min): 3.221683 in^3
Sy-y (min): 3.221683 in^3
Face<6> (Rectangle)
----------------------------------------
Width: 8.496827 in
Height: 8.591452 in
Area: 73.000082 in^2
Ix-x: 449.029856 in^4
Iy-y: 439.193284 in^4
J: 888.223139 in^4
rx-x: 2.480138 in
ry-y: 2.452823 in
Sx-x (min): 104.529448 in^3
Sy-y (min): 103.378183 in^3
Face<7> (Polygon (4 sides))
----------------------------------------
Area: 21.147473 in^2
Ix-x: 21.642900 in^4
Iy-y: 72.970277 in^4
J: 94.613177 in^4
rx-x: 1.011646 in
ry-y: 1.857564 in
Sx-x (min): 10.219749 in^3
Sy-y (min): 16.986716 in^3
Face<8> (Polygon (4 sides))
----------------------------------------
Area: 21.180454 in^2
Ix-x: 22.136407 in^4
Iy-y: 71.657071 in^4
J: 93.793478 in^4
rx-x: 1.022318 in
ry-y: 1.839339 in
Sx-x (min): 10.363989 in^3
Sy-y (min): 16.866783 in^3
Face<9> (Polygon (4 sides))
----------------------------------------
Area: 21.147473 in^2
Ix-x: 21.642900 in^4
Iy-y: 72.970277 in^4
J: 94.613177 in^4
rx-x: 1.011646 in
ry-y: 1.857564 in
Sx-x (min): 10.219749 in^3
Sy-y (min): 16.986716 in^3
======================================================================
RESULTS IN FT
======================================================================
Face<10> (Polygon (4 sides))
----------------------------------------
Area: 0.147086 ft^2
Ix-x: 0.001068 ft^4
Iy-y: 0.003456 ft^4
J: 0.004523 ft^4
rx-x: 0.085193 ft
ry-y: 0.153278 ft
Sx-x (min): 0.005998 ft^3
Sy-y (min): 0.009761 ft^3
Face<1> (Annulus)
----------------------------------------
Outer R: 0.062500 ft
Inner R: 0.052500 ft
Area: 0.003613 ft^2
Ix-x: 6.0176e-06 ft^4
Iy-y: 6.0176e-06 ft^4
J: 1.2035e-05 ft^4
rx-x: 0.040812 ft
ry-y: 0.040812 ft
Sx-x (min): 9.6282e-05 ft^3
Sy-y (min): 9.6282e-05 ft^3
Face<2> (Circle)
----------------------------------------
Radius: 0.062500 ft
Area: 0.012272 ft^2
Ix-x: 1.1984e-05 ft^4
Iy-y: 1.1984e-05 ft^4
J: 2.3968e-05 ft^4
rx-x: 0.031250 ft
ry-y: 0.031250 ft
Sx-x (min): 1.9175e-04 ft^3
Sy-y (min): 1.9175e-04 ft^3
Face<3> (Circle)
----------------------------------------
Radius: 0.052500 ft
Area: 0.008659 ft^2
Ix-x: 5.9666e-06 ft^4
Iy-y: 5.9666e-06 ft^4
J: 1.1933e-05 ft^4
rx-x: 0.026250 ft
ry-y: 0.026250 ft
Sx-x (min): 1.1365e-04 ft^3
Sy-y (min): 1.1365e-04 ft^3
Face<4> (Annulus)
----------------------------------------
Outer R: 0.104167 ft
Inner R: 0.062500 ft
Area: 0.021817 ft^2
Ix-x: 8.0487e-05 ft^4
Iy-y: 8.0487e-05 ft^4
J: 1.6097e-04 ft^4
rx-x: 0.060739 ft
ry-y: 0.060739 ft
Sx-x (min): 7.7267e-04 ft^3
Sy-y (min): 7.7267e-04 ft^3
Face<5> (Polygon (4 sides) with Hole)
----------------------------------------
Outer W: 0.250000 ft
Outer H: 0.250000 ft
Hole R: 0.104167 ft
Area: 0.028412 ft^2
Ix-x: 2.3305e-04 ft^4
Iy-y: 2.3305e-04 ft^4
J: 4.6610e-04 ft^4
rx-x: 0.090568 ft
ry-y: 0.090568 ft
Sx-x (min): 0.001864 ft^3
Sy-y (min): 0.001864 ft^3
Face<6> (Rectangle)
----------------------------------------
Width: 0.708069 ft
Height: 0.715954 ft
Area: 0.506945 ft^2
Ix-x: 0.021655 ft^4
Iy-y: 0.021180 ft^4
J: 0.042835 ft^4
rx-x: 0.206678 ft
ry-y: 0.204402 ft
Sx-x (min): 0.060492 ft^3
Sy-y (min): 0.059825 ft^3
Face<7> (Polygon (4 sides))
----------------------------------------
Area: 0.146857 ft^2
Ix-x: 0.001044 ft^4
Iy-y: 0.003519 ft^4
J: 0.004563 ft^4
rx-x: 0.084304 ft
ry-y: 0.154797 ft
Sx-x (min): 0.005914 ft^3
Sy-y (min): 0.009830 ft^3
Face<8> (Polygon (4 sides))
----------------------------------------
Area: 0.147086 ft^2
Ix-x: 0.001068 ft^4
Iy-y: 0.003456 ft^4
J: 0.004523 ft^4
rx-x: 0.085193 ft
ry-y: 0.153278 ft
Sx-x (min): 0.005998 ft^3
Sy-y (min): 0.009761 ft^3
Face<9> (Polygon (4 sides))
----------------------------------------
Area: 0.146857 ft^2
Ix-x: 0.001044 ft^4
Iy-y: 0.003519 ft^4
J: 0.004563 ft^4
rx-x: 0.084304 ft
ry-y: 0.154797 ft
Sx-x (min): 0.005914 ft^3
Sy-y (min): 0.009830 ft^3
======================================================================
END OF REPORT
======================================================================
@stephensmitchell

Copy link
Copy Markdown
Author

This is a debug script, so the length isn't as important, but it shouldn't grow more than this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment