# Armhole-scoop sweep for topTest1. Diagnostic, exports nothing. # # python tools/md_bridge.py --file tools/tailor/md_pari_armsweep.py --timeout 880 # # HYPOTHESIS (Jeremy's): the persistent diagonal crease across the back is surplus # WIDTH bunching where the two panels meet. The numbers say he's right, but not at # the bust or hem — those are matched: # bust 570 + 510 = 1080 vs bust 1083 (matched) # hem 380 + 320 = 700 vs waist 675 (+25 ease) # The surplus is ABOVE the bust. The panels stay near-full width up to the armhole # while the body narrows, giving ~968 mm of cloth around a much smaller torso at # underarm height. And the side seam only runs y 0..185, so above that the front and # back edges are FREE — nothing stops the surplus from overlapping and pushing a # diagonal fold across the back, which is exactly where the crease sits. # # Fix under test: a concave ARMHOLE SCYE. Insert one mid-point per armhole, pulled # inward by ARM, so the upper panel narrows without touching bust width, hem taper, # or strap position (moving the straps would re-expose the body's baked-in bra # straps, which is the whole reason the straps exist). # # Inserting points SHIFTS THE LINE INDICES, so indices are computed here rather than # hardcoded — hardcoded 0/5/7/9 has bitten this recipe twice already. # # 4 values x Simulate(250) ~= 4 min. PLAIN so shape is judged, not motif. import os import shutil import tempfile AVATAR_FBX = r"C:\Users\Jeremy\tinqs\animation\tools\tailor\avatar\Lena_QuatSkin_Avatar.fbx" ZFAB = r"C:\Users\Public\Documents\MarvelousDesigner\New Assets\Fabric\(Default for Simulation).zfab" W_FRONT, W_BACK = 570.0, 510.0 TOP = 350.0 SCOOP_FRONT, SCOOP_BACK = 105.0, 15.0 SIDE_Y = 185.0 TAPER = 95.0 ARM_H = 70.0 # mid-point sits ARM_H above SIDE_Y, i.e. y = 255 SWEEP = [0.0, 30.0, 55.0, 80.0] # mm pulled inward per side. 0 == current shape. SIDE_FLAGS = (True, True) SHOULDER_FLAGS = (False, False) ARR_X = 50 report = {"combos": {}, "hypothesis": "surplus width ABOVE the bust, free edges above SIDE_Y"} def build(width, scoop, dx, arm): """Return (pattern_id, idx) where idx names the line indices we must sew.""" c = width / 2.0 pts = [(c - 210.0, TOP - 25.0), # 0 strapL_outer (c - 120.0, TOP), # 1 strapL_inner line0 = SHOULDER_L (c - 70.0, TOP - scoop * 0.75), # 2 neck (c, TOP - scoop), # 3 neck (c + 70.0, TOP - scoop * 0.75), # 4 neck (c + 120.0, TOP), # 5 strapR_inner line5 = SHOULDER_R (c + 210.0, TOP - 25.0)] # 6 strapR_outer if arm: pts.append((width - arm, SIDE_Y + ARM_H)) # 7 armhole R mid (concave scye) pts += [(width, SIDE_Y), # sideR_top (width - TAPER, 0.0), # hemR (TAPER, 0.0), # hemL (0.0, SIDE_Y)] # sideL_top if arm: pts.append((arm, SIDE_Y + ARM_H)) # armhole L mid # line i runs pts[i] -> pts[i+1]; derive the seam indices from the layout n_arm = 1 if arm else 0 side_r = 6 + n_arm + 1 # sideR_top -> hemR hem = side_r + 1 side_l = hem + 1 # hemL -> sideL_top idx = {"shoulder_l": 0, "shoulder_r": 5, "side_r": side_r, "side_l": side_l, "hem": hem, "n_points": len(pts)} pid = pattern_api.CreatePatternWithPoints([(x + dx, y, 0) for (x, y) in pts]) return pid, idx for arm in SWEEP: key = "arm%02d" % int(arm) utility_api.NewProject() op = ApiTypes.ImportExportOption() op.scale = 10.0 op.bAddArrangementPoints = True op.bAutoTranslate = True import_api.ImportFBX(AVATAR_FBX, op) pf, ixf = build(W_FRONT, SCOOP_FRONT, 0.0, arm) pb, ixb = build(W_BACK, SCOOP_BACK, 900.0, arm) pattern_api.AddSeamlinePairGroup(pf, ixf["shoulder_l"], pb, ixb["shoulder_l"], *SHOULDER_FLAGS) pattern_api.AddSeamlinePairGroup(pf, ixf["shoulder_r"], pb, ixb["shoulder_r"], *SHOULDER_FLAGS) pattern_api.AddSeamlinePairGroup(pf, ixf["side_r"], pb, ixb["side_r"], *SIDE_FLAGS) pattern_api.AddSeamlinePairGroup(pf, ixf["side_l"], pb, ixb["side_l"], *SIDE_FLAGS) # Verify the computed indices actually point at the edges we think: shoulders # ~93 mm, sides ~208 mm. If these drift, the index math is wrong, not the cloth. lens = {k: [round(pattern_api.GetLineLength(pf, ixf[k]), 1), round(pattern_api.GetLineLength(pb, ixb[k]), 1)] for k in ("shoulder_l", "shoulder_r", "side_r", "side_l")} fab = fabric_api.AddFabric(ZFAB) for p in (pf, pb): pattern_api.SetPatternPieceFabricIndex(p, fab) arr = {a["ArrangementName"]: int(a["ArrangementIndex"]) for a in pattern_api.GetArrangementList()} pattern_api.SetArrangement(pf, arr["Body_Front_Center_1"]) pattern_api.SetArrangement(pb, arr["Body_Back_Center_1"]) pattern_api.SetArrangementPosition(pf, ARR_X, 55, 50) pattern_api.SetArrangementPosition(pb, ARR_X, 55, 50) utility_api.ResetClothArrangement() ok = utility_api.Simulate(250) utility_api.Refresh3DWindow() shots = export_api.ExportTurntableImages(4) saved = {} for i, label in ((0, "front"), (2, "back")): if i < len(shots) and os.path.exists(shots[i]): dst = os.path.join(tempfile.gettempdir(), "tinqs_armsweep_%s_%s.png" % (key, label)) shutil.copyfile(shots[i], dst) saved[label] = dst report["combos"][key] = {"sim": ok, "arm": arm, "idx_front": ixf, "seam_lengths": lens, "shots": saved} result = report