import pygarment as pyg from assets.garment_programs.circle_skirt import CircleArcPanel from assets.garment_programs import skirt_paneled from assets.garment_programs.base_classes import BaseBand class StraightBandPanel(pyg.Panel): """One panel for a panel skirt""" def __init__(self, name, width, depth, match_int_proportion=None) -> None: super().__init__(name) # define edge loop self.edges = pyg.EdgeSeqFactory.from_verts( [0, 0], [0, depth], [width, depth], [width, 0], loop=True) # define interface self.interfaces = { 'right': pyg.Interface(self, self.edges[0]), 'top': pyg.Interface(self, self.edges[1], ruffle=width / match_int_proportion if match_int_proportion is not None else 1. ).reverse(True), 'left': pyg.Interface(self, self.edges[2]), 'bottom': pyg.Interface(self, self.edges[3], ruffle=width / match_int_proportion if match_int_proportion is not None else 1. ) } # Default translation self.top_center_pivot() self.center_x() class StraightWB(BaseBand): """Simple 2 panel waistband""" def __init__(self, body, design, rise=1.) -> None: """Simple 2 panel waistband * rise -- the rise value of the bottoms that the WB is attached to Adapts the shape of the waistband to sit tight on top of the given rise level (top measurement). If 1. or anything less than waistband width, the rise is ignored and the StraightWB is created to sit well on the waist """ super().__init__(body, design, rise=rise) # Measurements self.waist = design['waistband']['waist']['v'] * body['waist'] self.waist_back_frac = body['waist_back_width'] / body['waist'] self.hips = body['hips'] * design['waistband']['waist']['v'] self.hips_back_frac = body['hip_back_width'] / body['hips'] # Params self.width = design['waistband']['width']['v'] self.rise = rise # Check correct values if self.rise + self.width > 1: self.rise = 1 - self.width self.top_width = pyg.utils.lin_interpolation( self.hips, self.waist, self.rise + self.width) self.top_back_fraction = pyg.utils.lin_interpolation( self.hips_back_frac, self.waist_back_frac, self.rise + self.width) self.width = self.width * body['hips_line'] self.define_panels() self.front.translate_by([0, body['_waist_level'] + 10, 20]) self.back.translate_by([0, body['_waist_level'] + 10, -20]) self.stitching_rules = pyg.Stitches( (self.front.interfaces['right'], self.back.interfaces['right']), (self.front.interfaces['left'], self.back.interfaces['left']) ) self.interfaces = { 'bottom_f': self.front.interfaces['bottom'], 'bottom_b': self.back.interfaces['bottom'], 'top_f': self.front.interfaces['top'], 'top_b': self.back.interfaces['top'], 'bottom': pyg.Interface.from_multiple( self.front.interfaces['bottom'], self.back.interfaces['bottom']), 'top': pyg.Interface.from_multiple( self.front.interfaces['top'], self.back.interfaces['top']), } def define_panels(self): back_width = self.top_width * self.top_back_fraction self.front = StraightBandPanel( 'wb_front', self.top_width - back_width, self.width, match_int_proportion=self.body['waist'] - self.body['waist_back_width'] ) self.back = StraightBandPanel( 'wb_back', back_width, self.width, match_int_proportion=self.body['waist_back_width'] ) class FittedWB(StraightWB): """Also known as Yoke: a waistband that ~follows the body curvature, and hence sits tight Made out of two circular arc panels """ def __init__(self, body, design, rise=1.) -> None: """A waistband that ~follows the body curvature, and hence sits tight * rise -- the rise value of the bottoms that the WB is attached to Adapts the shape of the waistband to sit tight on top of the given rise level. If 1. or anything less than waistband width, the rise is ignored and the FittedWB is created to sit well on the waist """ self.bottom_width = None self.bottom_back_fraction = None super().__init__(body, design, rise) def define_panels(self): self.bottom_width = pyg.utils.lin_interpolation( self.hips, self.waist, self.rise) self.bottom_back_fraction = pyg.utils.lin_interpolation( self.hips_back_frac, self.waist_back_frac, self.rise) self.front = CircleArcPanel.from_all_length( 'wb_front', self.width, self.top_width * (1 - self.top_back_fraction), self.bottom_width * (1 - self.bottom_back_fraction), match_top_int_proportion=self.body['waist'] - self.body['waist_back_width'], match_bottom_int_proportion=self.body['waist'] - self.body['waist_back_width'] ) self.back = CircleArcPanel.from_all_length( 'wb_back', self.width, self.top_width * self.top_back_fraction, self.bottom_width * self.bottom_back_fraction, match_top_int_proportion=self.body['waist_back_width'], match_bottom_int_proportion=self.body['waist_back_width'] ) class CuffBand(BaseBand): """ Cuff class for sleeves or pants band-like piece of fabric with optional "skirt" """ def __init__(self, tag, design, length=None) -> None: super().__init__(body=None, design=design, tag=tag) self.design = design['cuff'] if length is None: length = self.design['cuff_len']['v'] self.front = StraightBandPanel( f'{tag}_cuff_f', self.design['b_width']['v'] / 2, length) self.front.translate_by([0, 0, 15]) self.back = StraightBandPanel( f'{tag}_cuff_b', self.design['b_width']['v'] / 2, length) self.back.translate_by([0, 0, -15]) self.stitching_rules = pyg.Stitches( (self.front.interfaces['right'], self.back.interfaces['right']), (self.front.interfaces['left'], self.back.interfaces['left']) ) self.interfaces = { 'bottom': pyg.Interface.from_multiple( self.front.interfaces['bottom'], self.back.interfaces['bottom']), 'top_front': self.front.interfaces['top'], 'top_back': self.back.interfaces['top'], 'top': pyg.Interface.from_multiple( self.front.interfaces['top'], self.back.interfaces['top']), } class CuffSkirt(BaseBand): """A skirt-like flared cuff """ def __init__(self, tag, design, length=None) -> None: super().__init__(body=None, design=design, tag=tag) self.design = design['cuff'] width = self.design['b_width']['v'] flare_diff = (self.design['skirt_flare']['v'] - 1) * width / 2 if length is None: length = self.design['cuff_len']['v'] self.front = skirt_paneled.SkirtPanel( f'{tag}_cuff_skirt_f', ruffles=self.design['skirt_ruffle']['v'], waist_length=width / 2, length=length, flare=flare_diff) self.front.translate_by([0, 0, 15]) self.back = skirt_paneled.SkirtPanel( f'{tag}_cuff_skirt_b', ruffles=self.design['skirt_ruffle']['v'], waist_length=width / 2, length=length, flare=flare_diff) self.back.translate_by([0, 0, -15]) self.stitching_rules = pyg.Stitches( (self.front.interfaces['right'], self.back.interfaces['right']), (self.front.interfaces['left'], self.back.interfaces['left']) ) self.interfaces = { 'top': pyg.Interface.from_multiple( self.front.interfaces['top'], self.back.interfaces['top']), 'top_front': self.front.interfaces['top'], 'top_back': self.back.interfaces['top'], 'bottom': pyg.Interface.from_multiple( self.front.interfaces['bottom'], self.back.interfaces['bottom']), } class CuffBandSkirt(pyg.Component): """ Cuff class for sleeves or pants band-like piece of fabric with optional "skirt" """ def __init__(self, tag, design) -> None: super().__init__(self.__class__.__name__) self.cuff = CuffBand( tag, design, length=design['cuff']['cuff_len']['v'] * (1 - design['cuff']['skirt_fraction']['v']) ) self.skirt = CuffSkirt( tag, design, length=design['cuff']['cuff_len']['v'] * design['cuff']['skirt_fraction']['v'] ) # Align self.skirt.place_below(self.cuff) self.stitching_rules = pyg.Stitches( (self.cuff.interfaces['bottom'], self.skirt.interfaces['top']), ) self.interfaces = { 'top': self.cuff.interfaces['top'], 'top_front': self.cuff.interfaces['top_front'], 'top_back': self.cuff.interfaces['top_back'], 'bottom': self.skirt.interfaces['bottom'] } def length(self): return self.cuff.length() + self.skirt.length()