init_code
This commit is contained in:
674
assets/garment_programs/bodice.py
Normal file
674
assets/garment_programs/bodice.py
Normal file
@@ -0,0 +1,674 @@
|
||||
from copy import deepcopy
|
||||
import numpy as np
|
||||
|
||||
import pygarment as pyg
|
||||
|
||||
from assets.garment_programs.base_classes import BaseBodicePanel
|
||||
from assets.garment_programs import sleeves
|
||||
from assets.garment_programs import collars
|
||||
from assets.garment_programs import tee
|
||||
from scipy.spatial.transform import Rotation as R
|
||||
|
||||
class BodiceFrontHalf(BaseBodicePanel):
|
||||
def __init__(self, name, body, design) -> None:
|
||||
super().__init__(name, body, design)
|
||||
|
||||
m_bust = body['bust']
|
||||
m_waist = body['waist']
|
||||
|
||||
# sizes
|
||||
bust_point = body['bust_points'] / 2
|
||||
front_frac = (body['bust'] - body['back_width']) / 2 / body['bust']
|
||||
|
||||
self.width = front_frac * m_bust
|
||||
waist = (m_waist - body['waist_back_width']) / 2
|
||||
sh_tan = np.tan(np.deg2rad(body['_shoulder_incl']))
|
||||
shoulder_incl = sh_tan * self.width
|
||||
bottom_d_width = (self.width - waist) * 2 / 3
|
||||
|
||||
adjustment = sh_tan * (self.width - body['shoulder_w'] / 2)
|
||||
max_len = body['waist_over_bust_line'] - adjustment
|
||||
|
||||
# side length is adjusted due to shoulder inclination
|
||||
# for the correct sleeve fitting
|
||||
fb_diff = (front_frac - (0.5 - front_frac)) * body['bust']
|
||||
back_adjustment = sh_tan * (body['back_width'] / 2 - body['shoulder_w'] / 2)
|
||||
side_len = body['waist_line'] - back_adjustment - sh_tan * fb_diff
|
||||
|
||||
self.edges.append(pyg.EdgeSeqFactory.from_verts(
|
||||
[0, 0],
|
||||
[-self.width, 0],
|
||||
[-self.width, max_len],
|
||||
[0, max_len + shoulder_incl]
|
||||
))
|
||||
self.edges.close_loop()
|
||||
|
||||
# Side dart
|
||||
bust_line = body['waist_line'] - body['_bust_line']
|
||||
side_d_depth = 0.75 * (self.width - bust_point) # NOTE: calculated value
|
||||
side_d_width = max_len - side_len
|
||||
s_edge, side_interface = self.add_dart(
|
||||
pyg.EdgeSeqFactory.dart_shape(side_d_width, side_d_depth),
|
||||
self.edges[1],
|
||||
offset=bust_line + side_d_width / 2)
|
||||
self.edges.substitute(1, s_edge)
|
||||
|
||||
# Take some fabric from the top to match the shoulder width
|
||||
s_edge[-1].end[0] += (x_upd:=self.width - body['shoulder_w'] / 2)
|
||||
s_edge[-1].end[1] += (sh_tan * x_upd)
|
||||
|
||||
# Bottom dart
|
||||
b_edge, b_interface = self.add_dart(
|
||||
pyg.EdgeSeqFactory.dart_shape(bottom_d_width, 0.9 * bust_line),
|
||||
self.edges[0],
|
||||
offset=bust_point + bottom_d_width / 2
|
||||
)
|
||||
self.edges.substitute(0, b_edge)
|
||||
# Take some fabric from side in the bottom (!: after side dart insertion)
|
||||
b_edge[-1].end[0] = - (waist + bottom_d_width)
|
||||
|
||||
# Interfaces
|
||||
self.interfaces = {
|
||||
'outside': pyg.Interface(self, side_interface), # side_interface, # pyp.Interface(self, [side_interface]), #, self.edges[-3]]),
|
||||
'inside': pyg.Interface(self, self.edges[-1]),
|
||||
'shoulder': pyg.Interface(self, self.edges[-2]),
|
||||
'bottom': pyg.Interface(self, b_interface),
|
||||
|
||||
# Reference to the corner for sleeve and collar projections
|
||||
'shoulder_corner': pyg.Interface(
|
||||
self, [self.edges[-3], self.edges[-2]]),
|
||||
'collar_corner': pyg.Interface(
|
||||
self, [self.edges[-2], self.edges[-1]])
|
||||
}
|
||||
|
||||
# default placement
|
||||
self.translate_by([0, body['height'] - body['head_l'] - max_len - shoulder_incl, 0])
|
||||
|
||||
|
||||
class BodiceBackHalf(BaseBodicePanel):
|
||||
"""Panel for the back of basic fitted bodice block"""
|
||||
|
||||
def __init__(self, name, body, design) -> None:
|
||||
super().__init__(name, body, design)
|
||||
|
||||
# Overall measurements
|
||||
self.width = body['back_width'] / 2
|
||||
waist = body['waist_back_width'] / 2
|
||||
# NOTE: no inclination on the side, since there is not much to begin with
|
||||
waist_width = self.width if waist < self.width else waist
|
||||
shoulder_incl = (sh_tan:=np.tan(np.deg2rad(body['_shoulder_incl']))) * self.width
|
||||
|
||||
# Adjust to make sure length is measured from the shoulder
|
||||
# and not the de-fact side of the garment
|
||||
back_adjustment = sh_tan * (self.width - body['shoulder_w'] / 2)
|
||||
length = body['waist_line'] - back_adjustment
|
||||
|
||||
# Base edge loop
|
||||
edge_0 = pyg.CurveEdgeFactory.curve_from_tangents(
|
||||
start=[0, shoulder_incl / 4], # back a little shorter
|
||||
end=[-waist_width, 0],
|
||||
target_tan0=[-1, 0]
|
||||
)
|
||||
self.edges.append(edge_0)
|
||||
self.edges.append(pyg.EdgeSeqFactory.from_verts(
|
||||
edge_0.end,
|
||||
[-self.width, body['waist_line'] - body['_bust_line']], # from the bottom
|
||||
[-self.width, length],
|
||||
[0, length + shoulder_incl], # Add some fabric for the neck (inclination of shoulders)
|
||||
))
|
||||
self.edges.close_loop()
|
||||
|
||||
# Take some fabric from the top to match the shoulder width
|
||||
self.interfaces = {
|
||||
'outside': pyg.Interface(
|
||||
self, [self.edges[1], self.edges[2]]),
|
||||
'inside': pyg.Interface(self, self.edges[-1]),
|
||||
'shoulder': pyg.Interface(self, self.edges[-2]),
|
||||
'bottom': pyg.Interface(self, self.edges[0]),
|
||||
# Reference to the corners for sleeve and collar projections
|
||||
'shoulder_corner': pyg.Interface(
|
||||
self, pyg.EdgeSequence(self.edges[-3], self.edges[-2])),
|
||||
'collar_corner': pyg.Interface(
|
||||
self, pyg.EdgeSequence(self.edges[-2], self.edges[-1]))
|
||||
}
|
||||
|
||||
# Bottom dart as cutout -- for straight line
|
||||
if waist < self.get_width(self.edges[2].end[1] - self.edges[2].start[1]):
|
||||
w_diff = waist_width - waist
|
||||
side_adj = 0 if w_diff < 4 else w_diff / 6 # NOTE: don't take from sides if the difference is too small
|
||||
bottom_d_width = w_diff - side_adj
|
||||
bottom_d_width /= 2 # double darts
|
||||
bottom_d_depth = 1. * (length - body['_bust_line']) # calculated value
|
||||
bottom_d_position = body['bum_points'] / 2
|
||||
|
||||
# TODOLOW Avoid hardcoding for matching with the bottoms?
|
||||
dist = bottom_d_position * 0.5 # Dist between darts -> dist between centers
|
||||
b_edge, b_interface = self.add_dart(
|
||||
pyg.EdgeSeqFactory.dart_shape(bottom_d_width, 0.9 * bottom_d_depth),
|
||||
self.edges[0],
|
||||
offset=bottom_d_position + dist / 2 + bottom_d_width + bottom_d_width / 2,
|
||||
)
|
||||
b_edge, b_interface = self.add_dart(
|
||||
pyg.EdgeSeqFactory.dart_shape(bottom_d_width, bottom_d_depth),
|
||||
b_edge[0],
|
||||
offset=bottom_d_position - dist / 2 + bottom_d_width / 2,
|
||||
edge_seq=b_edge,
|
||||
int_edge_seq=b_interface,
|
||||
)
|
||||
|
||||
self.edges.substitute(0, b_edge)
|
||||
self.interfaces['bottom'] = pyg.Interface(self, b_interface)
|
||||
|
||||
# Remove fabric from the sides if the diff is big enough
|
||||
b_edge[-1].end[0] += side_adj
|
||||
|
||||
# default placement
|
||||
self.translate_by([0, body['height'] - body['head_l'] - length - shoulder_incl, 0])
|
||||
|
||||
def get_width(self, level):
|
||||
return self.width
|
||||
|
||||
class BodiceHalf(pyg.Component):
|
||||
"""Definition of a half of an upper garment with sleeves and collars"""
|
||||
|
||||
def __init__(self, name, body, design, fitted=True) -> None:
|
||||
super().__init__(name)
|
||||
|
||||
design = deepcopy(design) # Recalculate freely!
|
||||
|
||||
# Torso
|
||||
if fitted:
|
||||
self.ftorso = BodiceFrontHalf(
|
||||
f'{name}_ftorso', body, design).translate_by([0, 0, 30])
|
||||
self.btorso = BodiceBackHalf(
|
||||
f'{name}_btorso', body, design).translate_by([0, 0, -25])
|
||||
else:
|
||||
self.ftorso = tee.TorsoFrontHalfPanel(
|
||||
f'{name}_ftorso', body, design).translate_by([0, 0, 30])
|
||||
self.btorso = tee.TorsoBackHalfPanel(
|
||||
f'{name}_btorso', body, design).translate_by([0, 0, -25])
|
||||
|
||||
# Interfaces
|
||||
self.interfaces.update({
|
||||
'f_bottom': self.ftorso.interfaces['bottom'],
|
||||
'b_bottom': self.btorso.interfaces['bottom'],
|
||||
'front_in': self.ftorso.interfaces['inside'],
|
||||
'back_in': self.btorso.interfaces['inside']
|
||||
})
|
||||
|
||||
# Sleeves/collar cuts
|
||||
self.sleeve = None
|
||||
self.collar_comp = None
|
||||
self.eval_dep_params(body, design)
|
||||
|
||||
if design['fitted_shirt']['strapless']['v'] and fitted: # NOTE: Strapless design only for fitted tops
|
||||
self.make_strapless(body, design)
|
||||
else:
|
||||
# Sleeves and collars
|
||||
self.add_sleeves(name, body, design)
|
||||
self.add_collars(name, body, design)
|
||||
self.stitching_rules.append((
|
||||
self.ftorso.interfaces['shoulder'],
|
||||
self.btorso.interfaces['shoulder']
|
||||
)) # tops
|
||||
|
||||
# Main connectivity
|
||||
self.stitching_rules.append((
|
||||
self.ftorso.interfaces['outside'], self.btorso.interfaces['outside'])) # sides
|
||||
|
||||
def eval_dep_params(self, body, design):
|
||||
|
||||
# Sleeves
|
||||
# NOTE assuming the vertical side is the first argument
|
||||
max_cwidth = self.ftorso.interfaces['shoulder_corner'].edges[0].length() - 1 # cm
|
||||
min_cwidth = body['_armscye_depth']
|
||||
v = design['sleeve']['connecting_width']['v']
|
||||
design['sleeve']['connecting_width']['v'] = min(min_cwidth + min_cwidth * v, max_cwidth)
|
||||
|
||||
# Collars
|
||||
# NOTE: Assuming the first is the top edge
|
||||
# Width
|
||||
# TODOLOW What if sleeve inclination is variable?
|
||||
# NOTE: Back panel is more narrow, so using it
|
||||
max_w = body['_base_sleeve_balance'] - 2 # 1 cm from default sleeve
|
||||
min_w = body['neck_w']
|
||||
|
||||
if design['collar']['width']['v'] >= 0:
|
||||
design['collar']['width']['v'] = width = pyg.utils.lin_interpolation(min_w, max_w, design['collar']['width']['v'])
|
||||
else:
|
||||
design['collar']['width']['v'] = width = pyg.utils.lin_interpolation(0, min_w, 1 + design['collar']['width']['v'])
|
||||
|
||||
# Depth
|
||||
# Collar depth is given w.r.t. length.
|
||||
# adjust for the shoulder inclination
|
||||
tg = np.tan(np.deg2rad(body['_shoulder_incl']))
|
||||
f_depth_adj = tg * (self.ftorso.get_width(0) - width / 2)
|
||||
b_depth_adj = tg * (self.btorso.get_width(0) - width / 2)
|
||||
|
||||
max_f_len = self.ftorso.interfaces['collar_corner'].edges[1].length() - tg * self.ftorso.get_width(0) - 1 # cm
|
||||
max_b_len = self.btorso.interfaces['collar_corner'].edges[1].length() - tg * self.btorso.get_width(0) - 1 # cm
|
||||
|
||||
design['collar']['f_strapless_depth'] = {}
|
||||
design['collar']['f_strapless_depth']['v'] = min(
|
||||
design['collar']['fc_depth']['v'] * body['_bust_line'],
|
||||
max_f_len)
|
||||
design['collar']['fc_depth']['v'] = design['collar']['f_strapless_depth']['v'] + f_depth_adj
|
||||
|
||||
|
||||
design['collar']['b_strapless_depth'] = {}
|
||||
design['collar']['b_strapless_depth']['v'] = min(
|
||||
design['collar']['bc_depth']['v'] * body['_bust_line'],
|
||||
max_b_len)
|
||||
design['collar']['bc_depth']['v'] = design['collar']['b_strapless_depth']['v'] + b_depth_adj
|
||||
|
||||
def add_sleeves(self, name, body, design):
|
||||
self.sleeve = sleeves.Sleeve(
|
||||
name, body, design,
|
||||
front_w=self.ftorso.get_width,
|
||||
back_w=self.btorso.get_width
|
||||
)
|
||||
# self.sleeve = sleeves.OnePieceSleeve(
|
||||
# name, body, design,
|
||||
# front_w=self.ftorso.get_width,
|
||||
# back_w=self.btorso.get_width
|
||||
# )
|
||||
|
||||
_, f_sleeve_int = pyg.ops.cut_corner(
|
||||
self.sleeve.interfaces['in_front_shape'].edges,
|
||||
self.ftorso.interfaces['shoulder_corner'],
|
||||
verbose=self.verbose
|
||||
)
|
||||
_, b_sleeve_int = pyg.ops.cut_corner(
|
||||
self.sleeve.interfaces['in_back_shape'].edges,
|
||||
self.btorso.interfaces['shoulder_corner'],
|
||||
verbose=self.verbose
|
||||
)
|
||||
|
||||
if not design['sleeve']['sleeveless']['v']:
|
||||
# Ordering
|
||||
bodice_sleeve_int = pyg.Interface.from_multiple(
|
||||
f_sleeve_int.reverse(with_edge_dir_reverse=True),
|
||||
b_sleeve_int.reverse(),
|
||||
)
|
||||
self.stitching_rules.append((
|
||||
self.sleeve.interfaces['in'],
|
||||
bodice_sleeve_int
|
||||
))
|
||||
|
||||
# NOTE: This is a heuristic tuned for arm poses 30 deg-60 deg
|
||||
# used in the dataset
|
||||
# FIXME Needs a better general solution
|
||||
gap = -1 - body['arm_pose_angle'] / 10
|
||||
self.sleeve.place_by_interface(
|
||||
self.sleeve.interfaces['in'],
|
||||
bodice_sleeve_int,
|
||||
gap=gap,
|
||||
alignment='top',
|
||||
)
|
||||
|
||||
# Add edge labels
|
||||
f_sleeve_int.edges.propagate_label(f'{self.name}_armhole')
|
||||
b_sleeve_int.edges.propagate_label(f'{self.name}_armhole')
|
||||
|
||||
def add_collars(self, name, body, design):
|
||||
# Front
|
||||
collar_type = getattr(
|
||||
collars,
|
||||
str(design['collar']['component']['style']['v']),
|
||||
collars.NoPanelsCollar
|
||||
)
|
||||
|
||||
self.collar_comp = collar_type(name, body, design)
|
||||
|
||||
# Project shape
|
||||
_, fc_interface = pyg.ops.cut_corner(
|
||||
self.collar_comp.interfaces['front_proj'].edges,
|
||||
self.ftorso.interfaces['collar_corner'],
|
||||
verbose=self.verbose
|
||||
)
|
||||
_, bc_interface = pyg.ops.cut_corner(
|
||||
self.collar_comp.interfaces['back_proj'].edges,
|
||||
self.btorso.interfaces['collar_corner'],
|
||||
verbose=self.verbose
|
||||
)
|
||||
|
||||
# Add stitches/interfaces
|
||||
if 'bottom' in self.collar_comp.interfaces:
|
||||
self.stitching_rules.append((
|
||||
pyg.Interface.from_multiple(fc_interface, bc_interface),
|
||||
self.collar_comp.interfaces['bottom']
|
||||
))
|
||||
|
||||
# Upd front interfaces accordingly
|
||||
if 'front' in self.collar_comp.interfaces:
|
||||
self.interfaces['front_collar'] = self.collar_comp.interfaces['front']
|
||||
self.interfaces['front_in'] = pyg.Interface.from_multiple(
|
||||
self.ftorso.interfaces['inside'], self.interfaces['front_collar']
|
||||
)
|
||||
if 'back' in self.collar_comp.interfaces:
|
||||
self.interfaces['back_collar'] = self.collar_comp.interfaces['back']
|
||||
self.interfaces['back_in'] = pyg.Interface.from_multiple(
|
||||
self.btorso.interfaces['inside'], self.interfaces['back_collar']
|
||||
)
|
||||
|
||||
# Add edge labels
|
||||
fc_interface.edges.propagate_label(f'{self.name}_collar')
|
||||
bc_interface.edges.propagate_label(f'{self.name}_collar')
|
||||
|
||||
def make_strapless(self, body, design):
|
||||
|
||||
out_depth = design['sleeve']['connecting_width']['v']
|
||||
f_in_depth = design['collar']['f_strapless_depth']['v']
|
||||
b_in_depth = design['collar']['b_strapless_depth']['v']
|
||||
|
||||
# Shoulder adjustment for the back
|
||||
# TODOLOW Shoulder adj evaluation should be a function
|
||||
shoulder_angle = np.deg2rad(body['_shoulder_incl'])
|
||||
sleeve_balance = body['_base_sleeve_balance'] / 2
|
||||
back_w = self.btorso.get_width(0)
|
||||
shoulder_adj = np.tan(shoulder_angle) * (back_w - sleeve_balance)
|
||||
out_depth -= shoulder_adj
|
||||
|
||||
# Upd back
|
||||
self._adjust_top_level(self.btorso, out_depth, b_in_depth)
|
||||
|
||||
# Front depth determined by ~compensating for lenght difference
|
||||
len_back = self.btorso.interfaces['outside'].edges.length()
|
||||
len_front = self.ftorso.interfaces['outside'].edges.length()
|
||||
self._adjust_top_level(self.ftorso, out_depth, f_in_depth, target_remove=(len_front - len_back))
|
||||
|
||||
# Placement
|
||||
# NOTE: The commented line places the top a bit higher, increasing the chanced of correct drape
|
||||
# Surcumvented by attachment constraint, so removed for nicer alignment in asymmetric garments
|
||||
# self.translate_by([0, out_depth - body['_armscye_depth'] * 0.75, 0]) # adjust for better localisation
|
||||
|
||||
# Add a label
|
||||
self.ftorso.interfaces['shoulder'].edges.propagate_label('strapless_top')
|
||||
self.btorso.interfaces['shoulder'].edges.propagate_label('strapless_top')
|
||||
|
||||
|
||||
def _adjust_top_level(self, panel, out_level, in_level, target_remove=None):
|
||||
"""Crops the top of the bodice front/back panel for strapless style
|
||||
|
||||
* out_length_diff -- if set, determined the length difference that should be compensates
|
||||
after cutting the depth
|
||||
"""
|
||||
# TODOLOW Should this be the panel's function?
|
||||
|
||||
panel_top = panel.interfaces['shoulder'].edges[0]
|
||||
min_y = min(panel_top.start[1], panel_top.end[1])
|
||||
|
||||
# Order vertices
|
||||
ins, out = panel_top.start, panel_top.end
|
||||
if panel_top.start[1] < panel_top.end[1]:
|
||||
ins, out = out, ins
|
||||
|
||||
# Inside is a simple vertical line and can be adjusted by chaning Y value
|
||||
ins[1] = min_y - in_level
|
||||
|
||||
# Outside could be inclined, so needs further calculations
|
||||
outside_edge = panel.interfaces['outside'].edges[-1]
|
||||
bot, top = outside_edge.start, outside_edge.end
|
||||
if bot is out:
|
||||
bot, top = top, bot
|
||||
|
||||
if target_remove is not None:
|
||||
# Adjust the depth to remove this length exactly
|
||||
angle_sin = abs(out[1] - bot[1]) / outside_edge.length()
|
||||
curr_remove = out_level / angle_sin
|
||||
length_diff = target_remove - curr_remove
|
||||
adjustment = length_diff * angle_sin
|
||||
out_level += adjustment
|
||||
|
||||
angle_cotan = abs(out[0] - bot[0]) / abs(out[1] - bot[1])
|
||||
out[0] -= out_level * angle_cotan
|
||||
out[1] = min_y - out_level
|
||||
|
||||
|
||||
def length(self):
|
||||
return self.btorso.length()
|
||||
|
||||
class Shirt(pyg.Component):
|
||||
"""Panel for the front of upper garments with darts to properly fit it to
|
||||
the shape"""
|
||||
|
||||
def __init__(self, body, design, fitted=False) -> None:
|
||||
name_with_params = f"{self.__class__.__name__}"
|
||||
super().__init__(name_with_params)
|
||||
|
||||
design = self.eval_dep_params(design)
|
||||
|
||||
self.right = BodiceHalf(f'right', body, design, fitted=fitted)
|
||||
self.left = BodiceHalf(
|
||||
f'left', body,
|
||||
design['left'] if design['left']['enable_asym']['v'] else design,
|
||||
fitted=fitted).mirror()
|
||||
|
||||
self.stitching_rules.append((self.right.interfaces['front_in'],
|
||||
self.left.interfaces['front_in']))
|
||||
self.stitching_rules.append((self.right.interfaces['back_in'],
|
||||
self.left.interfaces['back_in']))
|
||||
|
||||
# Adjust interface ordering for correct connectivity
|
||||
self.interfaces = { # Bottom connection
|
||||
'bottom': pyg.Interface.from_multiple(
|
||||
self.right.interfaces['f_bottom'].reverse(),
|
||||
self.left.interfaces['f_bottom'],
|
||||
self.left.interfaces['b_bottom'].reverse(),
|
||||
self.right.interfaces['b_bottom'],)
|
||||
}
|
||||
|
||||
def eval_dep_params(self, design):
|
||||
# NOTE: Support for full collars with partially strapless top
|
||||
# or combination of paneled collar styles
|
||||
# requres further development
|
||||
# TODOLOW enable this one to work
|
||||
if design['left']['enable_asym']['v']:
|
||||
# Force no collars since they are not compatible with each other
|
||||
design = deepcopy(design)
|
||||
design['collar']['component']['style']['v'] = None
|
||||
design['left']['collar']['component'] = dict(style=dict(v=None))
|
||||
|
||||
# Left-right design compatibility
|
||||
design['left']['shirt'].update(length={})
|
||||
design['left']['shirt']['length']['v'] = design['shirt']['length']['v']
|
||||
|
||||
design['left']['collar'].update(fc_depth={}, bc_depth={})
|
||||
design['left']['collar']['fc_depth']['v'] = design['collar']['fc_depth']['v']
|
||||
design['left']['collar']['bc_depth']['v'] = design['collar']['bc_depth']['v']
|
||||
|
||||
return design
|
||||
|
||||
def length(self):
|
||||
return self.right.length()
|
||||
|
||||
class FittedShirt(Shirt):
|
||||
"""Creates fitted shirt
|
||||
|
||||
NOTE: Separate class is used for selection convenience.
|
||||
Even though most of the processing is the same
|
||||
(hence implemented with the same components except for panels),
|
||||
design parametrization differs significantly.
|
||||
With that, we decided to separate the top level names
|
||||
"""
|
||||
def __init__(self, body, design) -> None:
|
||||
super().__init__(body, design, fitted=True)
|
||||
|
||||
|
||||
class PrincessSeamShirt(pyg.Component):
|
||||
"""Class representing a shirt with princess seams."""
|
||||
|
||||
def __init__(self, body, design):
|
||||
# Initialize the base Component class
|
||||
super().__init__("PrincessSeamShirt")
|
||||
|
||||
# Evaluate design parameters
|
||||
self.eval_dep_params(design)
|
||||
|
||||
# Create front and back panels
|
||||
self.front_panel = self.create_front_panel(body, design)
|
||||
self.back_panel = self.create_back_panel(body, design)
|
||||
|
||||
# Add panels as components
|
||||
self.add_component(self.front_panel)
|
||||
self.add_component(self.back_panel)
|
||||
|
||||
# Define stitching rules
|
||||
self.stitching_rules = [
|
||||
# Side seams
|
||||
(self.front_panel.interfaces['side_seam'], self.back_panel.interfaces['side_seam']),
|
||||
# Shoulder seams
|
||||
(self.front_panel.interfaces['shoulder_seam'], self.back_panel.interfaces['shoulder_seam']),
|
||||
# Front princess seams
|
||||
(self.front_panel.interfaces['princess_seam_left'], self.front_panel.left_princess_panel.interfaces['princess_seam']),
|
||||
(self.front_panel.interfaces['princess_seam_right'], self.front_panel.right_princess_panel.interfaces['princess_seam']),
|
||||
# Back princess seams
|
||||
(self.back_panel.interfaces['princess_seam_left'], self.back_panel.left_princess_panel.interfaces['princess_seam']),
|
||||
(self.back_panel.interfaces['princess_seam_right'], self.back_panel.right_princess_panel.interfaces['princess_seam']),
|
||||
]
|
||||
|
||||
def eval_dep_params(self, design):
|
||||
# Placeholder for evaluating dependent design parameters
|
||||
pass
|
||||
|
||||
def create_front_panel(self, body, design):
|
||||
# Create the front panel
|
||||
front_panel = pyg.Panel("FrontPanel")
|
||||
|
||||
# Body measurements
|
||||
bust = body['bust']
|
||||
waist = body['waist']
|
||||
hips = body['hips']
|
||||
shoulder_width = body['shoulder_width']
|
||||
neck_width = body['neck_width']
|
||||
neck_depth = body['front_neck_depth']
|
||||
|
||||
# Calculate panel dimensions
|
||||
panel_width = bust / 2
|
||||
princess_seam_pos = bust / 8
|
||||
|
||||
# Define key points
|
||||
points = [
|
||||
[0, 0], # Bottom left
|
||||
[0, hips], # Hip point
|
||||
[0, waist], # Waist point
|
||||
[princess_seam_pos, bust], # Left bust point
|
||||
[shoulder_width / 2, bust + neck_depth], # Left shoulder
|
||||
[panel_width - shoulder_width / 2, bust + neck_depth], # Right shoulder
|
||||
[panel_width - princess_seam_pos, bust], # Right bust point
|
||||
[panel_width, waist], # Right waist point
|
||||
[panel_width, hips], # Right hip point
|
||||
[panel_width, 0], # Bottom right
|
||||
]
|
||||
|
||||
# Create edges
|
||||
edges = pyg.EdgeSequence()
|
||||
for i in range(len(points) - 1):
|
||||
edges.append(pyg.Edge(points[i], points[i + 1]))
|
||||
edges.append(pyg.Edge(points[-1], points[0])) # Close shape
|
||||
|
||||
# Assign edges to panel
|
||||
front_panel.edges = edges
|
||||
|
||||
# Define interfaces
|
||||
front_panel.interfaces = {
|
||||
'side_seam': pyg.Interface(front_panel, [edges[0], edges[8]]),
|
||||
'shoulder_seam': pyg.Interface(front_panel, [edges[4], edges[5]]),
|
||||
'princess_seam_left': pyg.Interface(front_panel, [edges[2]]),
|
||||
'princess_seam_right': pyg.Interface(front_panel, [edges[7]]),
|
||||
}
|
||||
|
||||
# Create princess panels
|
||||
front_panel.left_princess_panel = self.create_princess_panel(front_panel, edges[2], "FrontLeftPrincessPanel")
|
||||
front_panel.right_princess_panel = self.create_princess_panel(front_panel, edges[7], "FrontRightPrincessPanel")
|
||||
|
||||
return front_panel
|
||||
|
||||
def create_back_panel(self, body, design):
|
||||
# Create the back panel
|
||||
back_panel = pyg.Panel("BackPanel")
|
||||
|
||||
# Body measurements
|
||||
bust = body['bust']
|
||||
waist = body['waist']
|
||||
hips = body['hips']
|
||||
shoulder_width = body['shoulder_width']
|
||||
neck_width = body['neck_width']
|
||||
neck_depth = body['back_neck_depth']
|
||||
|
||||
# Calculate panel dimensions
|
||||
panel_width = bust / 2
|
||||
princess_seam_pos = bust / 8
|
||||
|
||||
# Define key points
|
||||
points = [
|
||||
[0, 0], # Bottom left
|
||||
[0, hips], # Hip point
|
||||
[0, waist], # Waist point
|
||||
[princess_seam_pos, bust], # Left bust point
|
||||
[shoulder_width / 2, bust + neck_depth], # Left shoulder
|
||||
[panel_width - shoulder_width / 2, bust + neck_depth], # Right shoulder
|
||||
[panel_width - princess_seam_pos, bust], # Right bust point
|
||||
[panel_width, waist], # Right waist point
|
||||
[panel_width, hips], # Right hip point
|
||||
[panel_width, 0], # Bottom right
|
||||
]
|
||||
|
||||
# Create edges
|
||||
edges = pyg.EdgeSequence()
|
||||
for i in range(len(points) - 1):
|
||||
edges.append(pyg.Edge(points[i], points[i + 1]))
|
||||
edges.append(pyg.Edge(points[-1], points[0])) # Close shape
|
||||
|
||||
# Assign edges to panel
|
||||
back_panel.edges = edges
|
||||
|
||||
# Define interfaces
|
||||
back_panel.interfaces = {
|
||||
'side_seam': pyg.Interface(back_panel, [edges[0], edges[8]]),
|
||||
'shoulder_seam': pyg.Interface(back_panel, [edges[4], edges[5]]),
|
||||
'princess_seam_left': pyg.Interface(back_panel, [edges[2]]),
|
||||
'princess_seam_right': pyg.Interface(back_panel, [edges[7]]),
|
||||
}
|
||||
|
||||
# Create princess panels
|
||||
back_panel.left_princess_panel = self.create_princess_panel(back_panel, edges[2], "BackLeftPrincessPanel")
|
||||
back_panel.right_princess_panel = self.create_princess_panel(back_panel, edges[7], "BackRightPrincessPanel")
|
||||
|
||||
return back_panel
|
||||
|
||||
def create_princess_panel(self, parent_panel, seam_edge, panel_name):
|
||||
# Create a princess panel along the seam
|
||||
princess_panel = pyg.Panel(panel_name)
|
||||
|
||||
# Seam edge points
|
||||
start_point = seam_edge.start
|
||||
end_point = seam_edge.end
|
||||
|
||||
# Panel offset
|
||||
offset = 5 # Width of the princess panel
|
||||
|
||||
# Calculate new points
|
||||
offset_start = [start_point[0] + offset, start_point[1]]
|
||||
offset_end = [end_point[0] + offset, end_point[1]]
|
||||
|
||||
# Create edges
|
||||
edges = pyg.EdgeSequence()
|
||||
edges.append(pyg.Edge(start_point, end_point)) # Seam edge
|
||||
edges.append(pyg.Edge(end_point, offset_end)) # Top edge
|
||||
edges.append(pyg.Edge(offset_end, offset_start)) # Outer edge
|
||||
edges.append(pyg.Edge(offset_start, start_point)) # Bottom edge
|
||||
|
||||
# Close shape
|
||||
edges.close_loop()
|
||||
|
||||
# Assign edges to panel
|
||||
princess_panel.edges = edges
|
||||
|
||||
# Define interfaces
|
||||
princess_panel.interfaces = {
|
||||
'princess_seam': pyg.Interface(princess_panel, [edges[0]]),
|
||||
'outer_seam': pyg.Interface(princess_panel, [edges[2]]),
|
||||
}
|
||||
|
||||
return princess_panel
|
||||
Reference in New Issue
Block a user