"""Broad tank-side stamp comparisons from manufacturer images;no fitted survey."""
from pathlib import Path
import copy,hashlib,json,math
import cadquery as cq
from front_wing_geometry import absolute_tessellation
ROOT=Path(__file__).resolve().parent;SOURCE='fuel-tank-reference';OUTPUT='fuel-tank-pressings-reference'
NAME='fuel_tank_hollow_shell_flange_seat_and_open_necks_comparison'
data=json.loads((ROOT/(SOURCE+'.json')).read_text());assembly=cq.Assembly.importStep(str(ROOT/(SOURCE+'.step')))
native={n:o.obj for n,o in assembly.objects.items()if o.obj is not None};old=native[NAME];new=old
T=data['manufacturer_envelope_reference']['listed_material_thickness_mm'];S=2032/2.4
DEPTH=data['manufacturer_envelope_reference']['listed_length_mm']-40
Z=-1.75*S;ROOF=data['mounting_datum_revision']['estimated_flange_top_y_mm']
PAN_HEIGHT=data['manufacturer_envelope_reference']['estimated_pan_height_mm'];CY=ROOF-PAN_HEIGHT/2
W,H,R,A,SHOULDER=60.,112.,8.,3.,8.
features=[]
def wire(w,h,r,cx,cy,z):
    base=cq.Workplane('XY').rect(w,h).val();rounded=base.fillet2D(r,base.Vertices())
    return rounded.translate((cx,cy,z))
for side in [-1,1]:
    wall=Z+side*DEPTH/2
    for cx in [-235.,0.,235.]:
        # A finite flat perimeter laps the retained sheet. Cosine-rise ruled shoulder
        # sections are selected morphology,not a measured stamping radius.
        wires=[wire(W,H,R,cx,CY,wall-side*3)]
        for i in range(13):
            u=i/12;rise=A*(1-math.cos(math.pi*u))/2
            wires.append(wire(W-2*SHOULDER*u,H-2*SHOULDER*u,R-2*u,cx,CY,wall+side*rise))
        outer=cq.Solid.makeLoft(wires,ruled=True)
        inner=outer.translate((0,0,-side*T))
        skin=outer.cut(inner)
        cut=cq.Solid.extrudeLinear(wire(W-1,H-1,R-.5,cx,CY,wall-side*2),[],cq.Vector(0,0,side*5))
        new=new.cut(cut).fuse(skin)
        features.append(dict(side=side,center_xy_mm=[cx,CY],old_wall_z_mm=wall,selected_width_height_mm=[W,H],selected_corner_radius_mm=R,selected_crown_mm=A,selected_shoulder_run_mm=SHOULDER))
new=new.clean();assert new.isValid()and len(new.Solids())==1
limits=('Manufacturer RO9F front/back photographs show three broad vertical stamped panels on each long pan face. '
        'They support morphology only,not fitted tank identity or a calibrated pressing map. '
        'Selected60x112mm footprints,8mm plan corner radius,3mm crown,8mm cosine-rise ruled shoulder run andX=-235/0/235mm centers are construction estimates. '
        'The old0.7366mm RO9F sheet reference is retained as a projected body-Z section;normal shoulder gauge,forming radii and sheet draw are not verified. '
        'Both sides repeat an estimated pattern without proving production symmetry or mapping product front/back to the actual car. '
        'Old tank bounds,flange,top/sender well,bottom,necks,feed port and ten other assembly groups stay. '
        'Body/filler/ELC/feed routes and their placements are not relocated or cut. Top-face stampings visible in the product image remain outside this side-panel increment. '
        'No fitted capacity,fluid seal,loaded support,body clearance,port identity,complete fuel circuit or verified replacement/removal path is established.')
revision=dict(manufacturer_source='https://ecat.spectrapremium.com/en/parts/RO9F',manufacturer_images=['https://ecat.spectrapremium.com/img/produits/RO9F_FRO_P01.jpg','https://ecat.spectrapremium.com/img/produits/RO9F_BAC_P01.jpg'],evidence='fuel-tank-pressings-evidence.json',owner_dimensions_applied=False,features=features,projected_z_section_mm=T,limits=limits,retained_source_sha256={ext:hashlib.sha256((ROOT/(SOURCE+ext)).read_bytes()).hexdigest()for ext in ['.json','.step']})
result=copy.deepcopy(data);out=cq.Assembly(name='tank_with_broad_side_pressing_comparisons')
for p in result['parts']:
    n=p['name'];shape=new if n==NAME else native[n];out.add(shape,name=n,color=cq.Color(*p['color']))
    if n==NAME:
        vs,ts=absolute_tessellation(shape,.08,.14);p['vertices']=[round(v,4)for pt in vs for v in pt.toTuple()];p['triangles']=[i for t in ts for i in t]
result['side_pressing_revision']=revision;result['limits']+=' '+limits
out.export(str(ROOT/(OUTPUT+'.step')));(ROOT/(OUTPUT+'.json')).write_text(json.dumps(result,separators=(',',':'))+'\n')
restored=cq.importers.importStep(str(ROOT/(OUTPUT+'.step'))).val();assert restored.isValid()and all(s.Volume()>0 for s in restored.Solids())
print(json.dumps(dict(groups=len(result['parts']),positive_solids=len(restored.Solids()),connected_tank=len(new.Solids())==1,old_volume_mm3=old.Volume(),new_volume_mm3=new.Volume())))
