component
LTC2945CMS#PBF - Wide Range I2C Power Monitor
Public Made by Adomby adom
Analog Devices (Linear Technology) LTC2945CMS#PBF: wide range I2C power monitor, 0 V to 80 V current and voltage sensing, 12-bit ADC, 24-bit power, min/max and alerts, split SDA for opto-isolation, 0 C to 70 C, MSOP-12. KiCad, Fusion and Altium libraries, 3D model and datasheet.
main
#!/usr/bin/env python3
"""Coarse OCCT tessellation of a component STEP written straight to a GLB (the "low" board LOD).
Meshes the exact B-rep with BRepMesh at a given linear / angular deflection (much coarser than step2glb's), keeps
the STEP's own face colours, one primitive per colour, Z up, millimetres -> metres, no recentring or rotation.
Materials are named and given physical PBR values by luminance like materials_bycolour.py (epoxy, pin-1 dimple,
matte tin). usage: coarse_glb.py part.step out.glb lin_mm ang_rad node_name (CadQuery python)"""
import sys, os, json, struct
import numpy as np
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import ortho
from OCP.BRepMesh import BRepMesh_IncrementalMesh
from OCP.BRepTools import BRepTools
step, out, lin, ang, name = sys.argv[1], sys.argv[2], float(sys.argv[3]), float(sys.argv[4]), sys.argv[5]
orig = ortho.BRepMesh_IncrementalMesh
def mesh(shp, _l, rel, _a, par):
BRepTools.Clean_s(shp); return orig(shp, lin, False, ang, True)
ortho.BRepMesh_IncrementalMesh = mesh
tris = ortho.load_tris(step)
groups = {}; order = []
for p, c in tris:
if c not in groups: groups[c] = []; order.append(c)
groups[c].append(p)
def mat(c):
lum = sum(c) / 3
if lum < 0.1: return {"name": "Adom.Body (epoxy)", "pbrMetallicRoughness": {"baseColorFactor": [*c, 1.0], "metallicFactor": 0.0, "roughnessFactor": 0.55}}
if lum < 0.5: return {"name": "Adom.Body (pin-1 dimple)", "pbrMetallicRoughness": {"baseColorFactor": [*c, 1.0], "metallicFactor": 0.0, "roughnessFactor": 0.75}}
return {"name": "Adom.Leads (matte tin)", "pbrMetallicRoughness": {"baseColorFactor": [0.72, 0.72, 0.70, 1.0], "metallicFactor": 1.0, "roughnessFactor": 0.35}}
bin_ = b""; views = []; accs = []; prims = []; ntri = 0
def view(data, target):
global bin_
off = len(bin_); bin_ += data
while len(bin_) % 4: bin_ += b"\0"
views.append({"buffer": 0, "byteOffset": off, "byteLength": len(data), "target": target}); return len(views) - 1
for mi, c in enumerate(order):
P = np.stack(groups[c])
n = np.cross(P[:, 1] - P[:, 0], P[:, 2] - P[:, 0]); n /= np.linalg.norm(n, axis=1, keepdims=True) + 1e-30
pos = (P.reshape(-1, 3) / 1000.0).astype(np.float32); nor = np.repeat(n, 3, axis=0).astype(np.float32)
key = np.concatenate([np.round(pos, 9), np.round(nor, 4)], 1)
uniq, inv = np.unique(key, axis=0, return_inverse=True)
up = uniq[:, :3].astype(np.float32); un = uniq[:, 3:].astype(np.float32)
idx = inv.astype(np.uint32).ravel()
a = view(up.tobytes(), 34962); b = view(un.tobytes(), 34962); i = view(idx.tobytes(), 34963)
accs += [{"bufferView": a, "componentType": 5126, "count": len(up), "type": "VEC3", "min": up.min(0).tolist(), "max": up.max(0).tolist()},
{"bufferView": b, "componentType": 5126, "count": len(un), "type": "VEC3"},
{"bufferView": i, "componentType": 5125, "count": len(idx), "type": "SCALAR"}]
prims.append({"attributes": {"POSITION": len(accs) - 3, "NORMAL": len(accs) - 2}, "indices": len(accs) - 1, "material": mi})
ntri += len(idx) // 3
gl = {"asset": {"version": "2.0", "generator": "coarse_glb.py (OCCT BRepMesh lin %.3f mm, ang %.2f rad)" % (lin, ang)},
"scene": 0, "scenes": [{"nodes": [0]}], "nodes": [{"name": name, "mesh": 0}], "meshes": [{"name": name, "primitives": prims}],
"materials": [mat(c) for c in order], "accessors": accs, "bufferViews": views, "buffers": [{"byteLength": len(bin_)}]}
js = json.dumps(gl, separators=(",", ":")).encode()
while len(js) % 4: js += b" "
open(out, "wb").write(struct.pack("<III", 0x46546C67, 2, 12 + 8 + len(js) + 8 + len(bin_)) + struct.pack("<II", len(js), 0x4E4F534A) + js + struct.pack("<II", len(bin_), 0x004E4942) + bin_)
print(json.dumps({"out": out, "triangles": ntri, "primitives": len(prims)}))