by adom
0603 SMD Green LED · 3.2 V drop · 25 mA max
master
John Lauer
Datasheet-true STEP height (0.55 mm), side MPN mark re-applied; GLBs, hero rebuilt without Z stretch
2e9a25d
20d ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
#!/usr/bin/env python3
"""Scale a STEP along ONE axis about a plane (default: z about z=0, the seating plane), keeping product names,
part colours and FACE colours (XCAF). Each leaf shape is scaled in world coordinates (its assembly location
applied, scaled, then moved back), so nested/rotated assemblies scale along the true world axis.
BRepBuilderAPI_GTransform is used (a non-uniform scale is not a rigid gp_Trsf); face colours are carried over
through the builder's Modified() history. Planes stay planes; cylinders become B-splines (unavoidable).
Usage: xcaf_scale_axis.py in.step out.step FACTOR [--axis z|y|x] [--origin 0]"""
import sys, argparse, re
from OCP.STEPCAFControl import STEPCAFControl_Reader, STEPCAFControl_Writer
from OCP.STEPControl import STEPControl_AsIs
from OCP.TDocStd import TDocStd_Document
from OCP.TCollection import TCollection_ExtendedString
from OCP.XCAFDoc import XCAFDoc_DocumentTool, XCAFDoc_ColorType
from OCP.TDF import TDF_ChildIterator, TDF_Label
from OCP.TopLoc import TopLoc_Location
from OCP.TopExp import TopExp_Explorer
from OCP.TopAbs import TopAbs_FACE
from OCP.Quantity import Quantity_Color
from OCP.gp import gp_GTrsf, gp_Mat, gp_XYZ
from OCP.BRepBuilderAPI import BRepBuilderAPI_GTransform
from OCP.Bnd import Bnd_Box
from OCP.BRepBndLib import BRepBndLib
ap = argparse.ArgumentParser(); ap.add_argument('src'); ap.add_argument('out'); ap.add_argument('factor', type=float)
ap.add_argument('--axis', default='z', choices=['x', 'y', 'z']); ap.add_argument('--origin', type=float, default=0.0); a = ap.parse_args()
i = 'xyz'.index(a.axis); k = a.factor
diag = [1.0, 1.0, 1.0]; diag[i] = k; tr = [0.0, 0.0, 0.0]; tr[i] = a.origin * (1 - k)
g = gp_GTrsf(); g.SetVectorialPart(gp_Mat(diag[0], 0, 0, 0, diag[1], 0, 0, 0, diag[2])); g.SetTranslationPart(gp_XYZ(*tr))
doc = TDocStd_Document(TCollection_ExtendedString("d"))
r = STEPCAFControl_Reader(); r.SetColorMode(True); r.SetNameMode(True); r.SetLayerMode(True); assert r.ReadFile(a.src) == 1; r.Transfer(doc)
st = XCAFDoc_DocumentTool.ShapeTool_s(doc.Main()); ct = XCAFDoc_DocumentTool.ColorTool_s(doc.Main())
SURF, GEN = XCAFDoc_ColorType.XCAFDoc_ColorSurf, XCAFDoc_ColorType.XCAFDoc_ColorGen
leaves = {}
def walk(l, loc):
if st.IsReference_s(l):
ref = TDF_Label(); st.GetReferredShape_s(l, ref); return walk(ref, loc.Multiplied(st.GetLocation_s(l)))
if st.IsAssembly_s(l):
it = TDF_ChildIterator(l, False)
while it.More(): c = it.Value(); it.Next(); walk(c, loc)
return
key = l.Tag()
if key in leaves: assert leaves[key][1].IsEqual(loc), 'a part instanced at two different locations cannot be scaled in place'
leaves[key] = (l, loc)
it = TDF_ChildIterator(st.Label(), False)
while it.More():
l = it.Value(); it.Next()
if st.IsFree_s(l) and st.IsTopLevel(l): walk(l, TopLoc_Location())
nf = 0
for l, loc in leaves.values():
s = st.GetShape_s(l)
fcols = [] # face colours of the ORIGINAL faces
ex = TopExp_Explorer(s, TopAbs_FACE)
while ex.More():
f = ex.Current(); ex.Next(); c = Quantity_Color(); got = None
for t in (SURF, GEN):
if ct.GetColor(f, t, c): got = (t, Quantity_Color(c.Red(), c.Green(), c.Blue(), __import__('OCP.Quantity', fromlist=['x']).Quantity_TOC_RGB)); break
if got: fcols.append((f, got))
mk = BRepBuilderAPI_GTransform(s.Moved(loc), g, True)
new = mk.Shape().Moved(loc.Inverted())
# map each coloured original face to its scaled image (history is on the moved copy)
mapped = []
for f, (t, c) in fcols:
img = mk.ModifiedShape(f.Moved(loc)).Moved(loc.Inverted())
mapped.append((img, t, c))
st.SetShape(l, new)
for img, t, c in mapped:
sub = st.AddSubShape(l, img)
if sub.IsNull(): continue
ct.SetColor(sub, c, SURF); ct.SetColor(sub, c, GEN); nf += 1
st.UpdateAssemblies()
w = STEPCAFControl_Writer(); w.SetColorMode(True); w.SetNameMode(True); w.SetLayerMode(True)
w.Transfer(doc, STEPControl_AsIs); assert w.Write(a.out) == 1
m = re.search(r'HEADER;\s*(/\*.*?\*/)', open(a.src, encoding='latin-1').read(), re.S) # keep the licence comment block
if m:
t = open(a.out, encoding='latin-1').read().replace('HEADER;', 'HEADER;\n' + m.group(1), 1); open(a.out, 'w', encoding='latin-1').write(t)
b = Bnd_Box()
for l, loc in leaves.values(): BRepBndLib.Add_s(st.GetShape_s(l).Moved(loc), b)
mn, mx = b.CornerMin(), b.CornerMax()
print(f'scaled {len(leaves)} part(s) by {k} along {a.axis} about {a.origin}; face colours carried {nf}; bbox x {mn.X():.4f}..{mx.X():.4f} y {mn.Y():.4f}..{mx.Y():.4f} z {mn.Z():.4f}..{mx.Z():.4f}')