195 lines
8.9 KiB
Python
195 lines
8.9 KiB
Python
|
|
from assets.garment_programs.tee import *
|
|||
|
|
from assets.garment_programs.godet import *
|
|||
|
|
from assets.garment_programs.bodice import *
|
|||
|
|
from assets.garment_programs.pants import *
|
|||
|
|
from assets.garment_programs.bands import *
|
|||
|
|
from assets.garment_programs.skirt_paneled import *
|
|||
|
|
from assets.garment_programs.skirt_levels import *
|
|||
|
|
from assets.garment_programs.circle_skirt import *
|
|||
|
|
from assets.garment_programs.sleeves import *
|
|||
|
|
import yaml
|
|||
|
|
class TotalLengthError(BaseException):
|
|||
|
|
"""Error indicating that the total length of a garment goes beyond
|
|||
|
|
the floor length for a given person"""
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
class IncorrectElementConfiguration(BaseException):
|
|||
|
|
"""Error indicating that given pattern is an empty garment"""
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
class MetaGarment(pyg.Component):
|
|||
|
|
"""Meta garment component
|
|||
|
|
Depending on parameter values it can generate sewing patterns
|
|||
|
|
for various dresses and jumpsuit styles and fit them to the body
|
|||
|
|
measurements
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
def __init__(self, name, body, design) -> None:
|
|||
|
|
super().__init__(name)
|
|||
|
|
self.body = body
|
|||
|
|
self.design = design
|
|||
|
|
# with open('assets/bodies/mean_all_full.yaml', 'w') as f:
|
|||
|
|
# yaml.dump(body, f, default_flow_style=False)
|
|||
|
|
# Elements
|
|||
|
|
self.upper_name = design['meta']['upper']['v']
|
|||
|
|
self.lower_name = design['meta']['bottom']['v']
|
|||
|
|
self.belt_name = design['meta']['wb']['v']
|
|||
|
|
|
|||
|
|
# Upper garment
|
|||
|
|
if self.upper_name:
|
|||
|
|
upper = globals()[self.upper_name]
|
|||
|
|
self.subs = [upper(body, design)]
|
|||
|
|
|
|||
|
|
# Set a label
|
|||
|
|
self.subs[-1].set_panel_label('body', overwrite=False)
|
|||
|
|
|
|||
|
|
#Pan up a bit:
|
|||
|
|
self.subs[-1].translate_by((0, 5, 0))
|
|||
|
|
|
|||
|
|
# Here are all the garments that are not connected to have a belt
|
|||
|
|
if self.belt_name == None:
|
|||
|
|
if design['meta']['connected']['v'] == False and design['meta']['bottom']['v'] != None:
|
|||
|
|
if design['meta']['bottom']['v'] != 'Pants':
|
|||
|
|
design['meta']['wb']['v'] = "FittedWB"
|
|||
|
|
design['waistband']['waist']['v'] = 0.7
|
|||
|
|
design['waistband']['width']['v'] = 0.1
|
|||
|
|
if design['meta']['bottom']['v'] == 'Pants':
|
|||
|
|
design['meta']['wb']['v'] = 'FittedWB'
|
|||
|
|
design['waistband']['waist']['v'] = 1
|
|||
|
|
design['waistband']['width']['v'] = 0.2
|
|||
|
|
self.belt_name = design['meta']['wb']['v']
|
|||
|
|
|
|||
|
|
# Define Lower garment
|
|||
|
|
if self.lower_name:
|
|||
|
|
Lower_class = globals()[self.lower_name]
|
|||
|
|
# NOTE: full rise for fitted tops
|
|||
|
|
Lower = Lower_class(body, design, rise=1. if self.upper_name and 'Fitted' in self.upper_name else None)
|
|||
|
|
else:
|
|||
|
|
Lower = None
|
|||
|
|
# Belt (or not)
|
|||
|
|
# TODO Adapt the rise of the lower garment to the width of the belt for correct matching
|
|||
|
|
if self.belt_name:
|
|||
|
|
Belt_class = globals()[self.belt_name]
|
|||
|
|
|
|||
|
|
# Adjust rise to match the Lower garment if needed
|
|||
|
|
Belt = Belt_class(body, design, Lower.get_rise() if Lower else 1.)
|
|||
|
|
|
|||
|
|
self.subs.append(Belt)
|
|||
|
|
# Place below the upper garment
|
|||
|
|
if len(self.subs) > 1:
|
|||
|
|
self.subs[-1].place_by_interface(
|
|||
|
|
self.subs[-1].interfaces['top'],
|
|||
|
|
self.subs[-2].interfaces['bottom'],
|
|||
|
|
gap=5
|
|||
|
|
)
|
|||
|
|
if design['meta']['connected']['v'] : # If you need to connect, you need to connect the belt to the top
|
|||
|
|
self.stitching_rules.append(
|
|||
|
|
(self.subs[-2].interfaces['bottom'],
|
|||
|
|
self.subs[-1].interfaces['top']))
|
|||
|
|
# Add waist label
|
|||
|
|
self.subs[-1].interfaces['top'].edges.propagate_label('lower_interface')
|
|||
|
|
# Set panel segmentation labels
|
|||
|
|
self.subs[-1].set_panel_label('body', overwrite=False)
|
|||
|
|
if self.lower_name:
|
|||
|
|
self.subs.append(Lower)
|
|||
|
|
# Place below the upper garment or self.wb
|
|||
|
|
if len(self.subs) > 1:
|
|||
|
|
self.subs[-1].place_by_interface(
|
|||
|
|
self.subs[-1].interfaces['top'],
|
|||
|
|
self.subs[-2].interfaces['bottom'],
|
|||
|
|
gap=5
|
|||
|
|
)
|
|||
|
|
#There must be a belt now, so here's how to connect the belt to the bottom
|
|||
|
|
self.stitching_rules.append(
|
|||
|
|
(self.subs[-2].interfaces['bottom'],
|
|||
|
|
self.subs[-1].interfaces['top']))
|
|||
|
|
#To deal with the simulation impact caused by the lack of connection, the main thing is to adjust the position and all the next translationby is to simulate better and reduce the problem situation.
|
|||
|
|
# The specific tranlateby values are mainly tried
|
|||
|
|
if not design['meta']['connected']['v']:
|
|||
|
|
self.handle_disconnected_position_influence(design)
|
|||
|
|
# Add waist label
|
|||
|
|
if not self.belt_name:
|
|||
|
|
self.subs[-1].interfaces['top'].edges.propagate_label('lower_interface')
|
|||
|
|
# Set panel segmentation labels
|
|||
|
|
self.subs[-1].set_panel_label('leg', overwrite=False)
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
def handle_disconnected_position_influence(self, design):
|
|||
|
|
'''deal with the influence of disconnected garments on the simulation by translateby .
|
|||
|
|
which is value is tried out'''
|
|||
|
|
self.subs[-1].translate_by((0, 6, 0))
|
|||
|
|
# Gets a specific clothing object
|
|||
|
|
pant_flag = False
|
|||
|
|
pant = None
|
|||
|
|
circleskirt = None
|
|||
|
|
circleskirt_flag = False
|
|||
|
|
shirt = None
|
|||
|
|
shirt_flag = False
|
|||
|
|
for sub in self.subs:
|
|||
|
|
if isinstance(sub, Pants):
|
|||
|
|
pant_flag = True
|
|||
|
|
pant = sub
|
|||
|
|
if isinstance(sub, SkirtCircle):
|
|||
|
|
circleskirt = sub
|
|||
|
|
circleskirt_flag = True
|
|||
|
|
if isinstance(sub, Shirt):
|
|||
|
|
shirt = sub
|
|||
|
|
shirt_flag = True
|
|||
|
|
if pant_flag and shirt_flag:
|
|||
|
|
|
|||
|
|
# If the top is short<=1.2, you need to pan the pants downward.
|
|||
|
|
if design['shirt']['length']['v'] <= 1.2:
|
|||
|
|
# pass
|
|||
|
|
pant.translate_by((0, -13, 0))
|
|||
|
|
# For clothes that are too long, pull them up
|
|||
|
|
if design['shirt']['length'][
|
|||
|
|
'v'] > 1.2:
|
|||
|
|
pant.translate_by((0, 25, 0))
|
|||
|
|
translate_d = 8
|
|||
|
|
shirt.right.ftorso.translate_by((0, 0, translate_d))
|
|||
|
|
shirt.right.btorso.translate_by((0, 0, -translate_d))
|
|||
|
|
shirt.left.ftorso.translate_by((0, 0, translate_d))
|
|||
|
|
shirt.left.btorso.translate_by((0, 0, -translate_d))
|
|||
|
|
# For the handling that is not underwear
|
|||
|
|
if design['meta']['bottom']['v'] is not None and design['meta']['bottom']['v'] != 'Pants':
|
|||
|
|
translate_d = 10
|
|||
|
|
bottom_garment = self.subs[-1]
|
|||
|
|
# if design['meta']['bottom']['v'] != "SkirtManyPanels":
|
|||
|
|
# bottom_garment.translate_by((0, 0, 0))
|
|||
|
|
# Deal with a single class first, for multiple skirts such as level, this is not processed, and later, at present, multi-layer group skirts do not need to be processed
|
|||
|
|
if (design['meta']['bottom']['v'] == "Skirt2 " or design['meta']['bottom']['v'] == "SkirtCircle"
|
|||
|
|
or design['meta']['bottom']['v'] == "AssymmSkirtCircle"
|
|||
|
|
or design['meta']['bottom']['v'] == "PencilSkirt"):
|
|||
|
|
bottom_garment.front.translate_by((0, 0, translate_d))
|
|||
|
|
bottom_garment.back.translate_by((0, 0, -translate_d))
|
|||
|
|
bottom_garment.translate_by((0, -8, 0))
|
|||
|
|
# For the handling of the pants
|
|||
|
|
if pant_flag:
|
|||
|
|
pant.translate_by((0, -8, 0))
|
|||
|
|
|
|||
|
|
|
|||
|
|
def assert_total_length(self, tol=1):
|
|||
|
|
"""Check the total length of components"""
|
|||
|
|
# Check that the total length of the components are less that body height
|
|||
|
|
length = self.length()
|
|||
|
|
floor = self.body['height'] - self.body['head_l']
|
|||
|
|
if length > floor + tol:
|
|||
|
|
raise TotalLengthError(f'{self.__class__.__name__}::{self.name}::ERROR:'
|
|||
|
|
f':Total length {length} exceeds the floor length {floor}')
|
|||
|
|
|
|||
|
|
# TODO these checks don't require initialization of the pattern!
|
|||
|
|
def assert_non_empty(self, filter_belts=True):
|
|||
|
|
"""Check that the garment is non-empty
|
|||
|
|
* filter_wb -- if set, then garments consisting only of waistbands are considered empty
|
|||
|
|
"""
|
|||
|
|
if not self.upper_name and not self.lower_name:
|
|||
|
|
if filter_belts or not self.belt_name:
|
|||
|
|
raise IncorrectElementConfiguration()
|
|||
|
|
|
|||
|
|
def assert_skirt_waistband(self):
|
|||
|
|
"""Check if a generated heavy skirt is created with a waistband"""
|
|||
|
|
|
|||
|
|
if self.lower_name and self.lower_name in ['SkirtCircle', 'AsymmSkirtCircle', 'SkirtManyPanels']:
|
|||
|
|
if not (self.belt_name or self.upper_name):
|
|||
|
|
raise IncorrectElementConfiguration()
|