Skip to content

Instantly share code, notes, and snippets.

@zeffii
Created May 9, 2025 07:11
Show Gist options
  • Save zeffii/6f522f87c568113c6926aa1c6be1013a to your computer and use it in GitHub Desktop.
Save zeffii/6f522f87c568113c6926aa1c6be1013a to your computer and use it in GitHub Desktop.
decompose_no_classify_yet
'''
in verts v
in faces s
out v_out v
out e_out s
'''
import numpy as np
def find_cylinder_endpoints(vertices, faces):
# Convert vertices to NumPy for efficiency
v = np.array(vertices)
# Extract boundary edges (those shared by only one face)
edge_count = {}
for face in faces:
for i in range(len(face)):
edge = tuple(sorted((face[i], face[(i + 1) % len(face)])))
edge_count[edge] = edge_count.get(edge, 0) + 1
boundary_edges = [e for e, count in edge_count.items() if count == 1]
# Group boundary edges into loops
loops = find_edge_loops(boundary_edges)
# Output vertex centers (approximate endpoints)
v_out = [np.mean(v[loop], axis=0) for loop in loops]
e_out = [(i, i + 1) for i in range(0, len(v_out), 2)]
return v_out, e_out
def find_edge_loops(edges):
# Find all edge-connected loops
edge_map = {}
for e1, e2 in edges:
edge_map.setdefault(e1, []).append(e2)
edge_map.setdefault(e2, []).append(e1)
loops = []
visited = set()
for start in edge_map:
if start in visited:
continue
loop = []
current = start
while current not in visited:
visited.add(current)
loop.append(current)
next_candidates = [n for n in edge_map[current] if n not in visited]
if not next_candidates:
break
current = next_candidates[0]
loops.append(loop)
return loops
for vlist, flist in zip(verts, faces):
pts = find_cylinder_endpoints(vlist, flist)
nverts, nedges = pts
nnverts = [n.tolist() for n in nverts]
v_out.append(nnverts)
e_out.append(nedges)
@zeffii
Copy link
Author

zeffii commented May 9, 2025

semi classifier

"""
in verts v
in faces s
out verts_out v
out edges_out s
"""

import mathutils

# Function to detect complex objects based on vertex sharing
def is_complex_object(faces, max_shared_faces=3):
    vertex_face_count = {}
    for face in faces:
        for vert_idx in face:
            if vert_idx not in vertex_face_count:
                vertex_face_count[vert_idx] = 0
            vertex_face_count[vert_idx] += 1
            # Early exit if a vertex is shared too many times
            if vertex_face_count[vert_idx] > max_shared_faces:
                return True
    return False

# Check if the input object is complex
if is_complex_object(faces, max_shared_faces=3):
    verts_out = []
    edges_out = []
    print("Complex object detected. Skipping.")
else:
    # Extract edges from faces
    edges = set()
    for face in faces:
        for i in range(len(face)):
            a, b = face[i], face[(i + 1) % len(face)]
            edges.add(tuple(sorted((a, b))))
    edges = list(edges)
    
    # Identify endpoints as vertices connected to only one edge (caps)
    edge_count = {i: 0 for i in range(len(verts))}
    for edge in edges:
        edge_count[edge[0]] += 1
        edge_count[edge[1]] += 1
    endpoint_indices = [idx for idx, count in edge_count.items() if count == 1]
    verts_out = [verts[idx] for idx in endpoint_indices]
    
    # Filter out closely spaced vertices to avoid noisy endpoints
    threshold = 0.001  # Adjust as needed for your mesh scale
    distinct_endpoints = []
    seen = set()
    for i, v in enumerate(verts_out):
        if i in seen:
            continue
        for j, u in enumerate(verts_out[i+1:], start=i+1):
            if (v - u).length < threshold:
                seen.add(j)
        distinct_endpoints.append(v)
    verts_out = distinct_endpoints

    # Keep only the edges connected to distinct endpoints
    endpoint_indices = set(endpoint_indices)
    edges_out = [e for e in edges if e[0] in endpoint_indices or e[1] in endpoint_indices]

    print(f"Extracted {len(verts_out)} endpoints and {len(edges_out)} edge connections.")

@zeffii
Copy link
Author

zeffii commented May 9, 2025

and another

from typing import List, Tuple, Dict
import numpy as np

def create_bounding_box(verts: List[Tuple[float, float, float]], faces: List[Tuple[int, int, int]]) -> Dict[str, Tuple[float, float, float]]:
    # Convert to NumPy array for efficient min/max operations
    verts_array = np.array(verts)
    min_coords = np.min(verts_array, axis=0)
    max_coords = np.max(verts_array, axis=0)
    # Return bounding box as a dictionary
    return {
        'min': tuple(min_coords),
        'max': tuple(max_coords)
    }

def validate_verts_within_bbox(bbox: Dict[str, Tuple[float, float, float]], verts: List[Tuple[float, float, float]]) -> Dict[str, str]:
    min_coords, max_coords = np.array(bbox['min']), np.array(bbox['max'])
    for vert in verts:
        if not np.all(min_coords <= vert) or not np.all(vert <= max_coords):
            return {'exceeds'}
    return {'valid'}

@zeffii
Copy link
Author

zeffii commented May 16, 2025

alvarez

{
	"dataVersion": 42,
	"settings": {
		"units": {
			"length": "m",
			"section_length": "mm",
			"material_strength": "mpa",
			"density": "kg/m3",
			"force": "kn",
			"moment": "kn-m",
			"pressure": "kpa",
			"mass": "kg",
			"temperature": "degc",
			"translation": "mm",
			"stress": "mpa"
		},
		"precision": "fixed",
		"precision_values": 3,
		"evaluation_points": 9,
		"apply_evaluation_points_to_continuous_member_spans": true,
		"continuous_member_node_detection_tolerance": "0",
		"vertical_axis": "Y",
		"member_offsets_axis": "local",
		"projection_system": "orthographic",
		"solver_timeout": 1200,
		"linear_equation_solver": "direct_1",
		"smooth_plate_nodal_results": true,
		"extrapolate_plate_results_from_gauss_points": true,
		"calculate_shear_properties_of_wood_concrete_sections": false,
		"buckling_johnson": false,
		"non_linear_tolerance": "1",
		"non_linear_theory": "small",
		"auto_stabilize_model": false,
		"only_solve_user_defined_load_combinations": false,
		"include_rigid_links_for_area_loads": false,
		"include_inner_members_for_two_way_area_loads": false,
		"dynamic_modes": "10",
		"dynamic_frequency_area_reduction_factor": "1",
		"envelope_alternate_method": true,
		"thumbnail": {
			"visibility": {
				"nodes": true,
				"node_labels": true,
				"member_labels": true,
				"supports": true,
				"loads": true,
				"load_labels": true
			}
		},
		"visibility": {
			"nodes": true,
			"node_labels": true,
			"members": true,
			"member_labels": true,
			"member_end_fixities": true,
			"rigid_links": true,
			"plates": true,
			"plate_labels": true,
			"mesh": true,
			"mesh_nodes": true,
			"supports": true,
			"support_labels": false,
			"support_fixity_labels": false,
			"loads": true,
			"load_labels": true,
			"local_axis": false,
			"graphics_font_size": "3"
		}
	},
	"details": {
		"name": "Project Workflow",
		"designer": "D.M",
		"notes": "sections for pipes, connections, and proprietary member profiles"
	},
	"nodes": {},
	"members": {},
	"plates": {},
	"meshed_plates": {},
	"materials": {},
	"sections": {},
	"supports": {},
	"settlements": {},
	"groups": {},
	"point_loads": {},
	"moments": {},
	"distributed_loads": {},
	"pressures": {},
	"area_loads": {},
	"member_prestress_loads": {},
	"thermal_loads": {},
	"self_weight": {},
	"load_combinations": {},
	"load_cases": {},
	"nodal_masses": {},
	"nodal_masses_conversion_map": {},
	"spectral_loads": {},
	"notional_loads": {},
	"suppress": {
		"All On": {
			"members": [],
			"plates": [],
			"supports": [],
			"moments": [],
			"distributed_loads": [],
			"point_loads": [],
			"area_loads": [],
			"pressures": [],
			"load_combinations": []
		},
		"User Defined": {
			"members": [],
			"plates": [],
			"supports": [],
			"moments": [],
			"distributed_loads": [],
			"point_loads": [],
			"area_loads": [],
			"pressures": [],
			"load_combinations": []
		},
		"current_case": "User Defined"
	},
	"gridlines_and_elevations": [],
	"design_input": {}
}

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