def mkattach(self, obj, mode = 'p'): if mode == 'p': dname = Globals.getAttachProp(obj['$.name'], 'd') tname = Globals.getAttachProp(obj['$.name'], 'theta') # The angle will always be constant and relative to the # angular position of the body t = self.symbols.getSymbol(self.name, tname) d = self.symbols.getSymbol(self.name, dname, nonnegative=True) # (distance from center of mass, angle) return (d, t, mode) elif mode == 'r': xname = Globals.getAttachProp(obj['$.name'], 'x') yname = Globals.getAttachProp(obj['$.name'], 'y') # Without moment of inertia, the attachment position will be constant x = self.symbols.getSymbol(self.name, xname) y = self.symbols.getSymbol(self.name, yname) # (x distance from center of mass, y distance from center of mass) return (x, y, mode) else: raise Exception('invalid attachment mode %s' % str(mode))
def loadDynamic(self, name, props, data, aliases): dyn = data["dynamic"] bodies = [self.getObject(n[0]) for n in data["attach"]] attmodes = [n[1] if len(n) > 1 else "p" for n in data["attach"]] attoffs = [n[2] if len(n) > 1 else None for n in data["attach"]] offs = data["offset"] showangles = props.get("showangles", False) # A few assert funtions... def assert_bodies(name, n): if len(bodies) != n: raise Exception("%s dynamic expects %d body, provided %d" % (name, n, len(bodies))) def assert_offs(name, n): if len(offs) != n: raise Exception("%s dynamic expects %d offsets, provided %d" % (name, n, len(offs))) def aliasify(s, p): alias = aliases.get(s, None) if alias != None: self.aliases[p] = alias return str(p) # Roll assertions def get0Rolls(what): roll = props.get("roll", None) if roll == None: roll = props.get("rolla", None) if roll == "1" or roll == "1": self.printer.print_diagnostic(2, "dynamic %s does not have roll because it is %s." % (name, what)) def get1Roll(): roll = props.get("roll", None) if roll == None: roll = props.get("rolla", None) if roll == "1" or roll == "1": self.printer.print_diagnostic( 3, "dynamic %s set to roll mode on body %s." % (name, bodies[0]["$.name"]) ) roll = True else: roll = False return roll def get2Rolls(): rolla = props.get("rolla", None) if rolla == "1" or rolla == "1": self.printer.print_diagnostic( 3, "dynamic %s set to roll mode on body %s." % (name, bodies[0]["$.name"]) ) rolla = True else: rolla = False rollb = props.get("rollb", None) if rollb == "1" or rollb == "1": self.printer.print_diagnostic( 3, "dynamic %s set to roll mode on body %s." % (name, bodies[1]["$.name"]) ) rollb = True else: rollb = False return (rolla, rollb) # Resolve the attachments for b, m, o in zip(bodies, attmodes, attoffs): if o != None: if m == "p": ata = Globals.getAttachProp(b["$.name"], "d") atb = Globals.getAttachProp(b["$.name"], "theta") elif m == "r": ata = Globals.getAttachProp(b["$.name"], "x") atb = Globals.getAttachProp(b["$.name"], "y") self.symbols.addReplacement(name, ata, o[0]) self.symbols.addReplacement(name, atb, o[1]) # Switch the dynamic type if dyn == "force": assert_bodies("force", 1) assert_offs("force", 4) pos = (offs["x1"], offs["y1"], offs["x2"], offs["y2"]) att = (bodies[0], attmodes[0]) # Constant Force has only one roll roll = get1Roll() d = Dynamics.ForceDynamic(name, att, roll, self.symbols) t = aliasify("theta", d.theta) title = aliasify("F", d.getFSym()) elif dyn == "weight": # TODO ignore offset and force it to center of mass assert_bodies("weight", 1) assert_offs("weight", 4) pos = (offs["x1"], offs["y1"], offs["x2"], offs["y2"]) # Weight Force only has an att if the center of mass is different # from the fixture point, which means the translation axes MUST # be fixed, enforce this rule # By default the attachment must be zero even if nothing is # specified (center of mass assumed) mustlock = True # Enforce att lock if the axes are not if not isTimeConstant(bodies[0]["tr.x"], self.symbols) or not isTimeConstant( bodies[0]["tr.y"], self.symbols ): if attoffs[0] != None: self.printer.print_diagnostic( 2, "offset for %s will be ignored because the body %s is not locked in x and y." % (name, bodies[0]["$.name"]), ) else: if attoffs[0] != None: mustlock = False if mustlock: attmodes[0] = "p" ata = Globals.getAttachProp(b["$.name"], "d") atb = Globals.getAttachProp(b["$.name"], "theta") self.symbols.addReplacement(name, ata, 0) self.symbols.addReplacement(name, atb, 0) att = (bodies[0], attmodes[0]) # Weight Force only has no rolls :/ get0Rolls("weight") d = Dynamics.WeightDynamic(name, att, self.symbols) title = str(d.getFSym()) showangles = False # Do not show theta for gravity elif dyn == "rod": assert_bodies("rod", 2) assert_offs("rod", 4) pos = (offs["x1"], offs["y1"], offs["x2"], offs["y2"]) att0 = (bodies[0], attmodes[0]) att1 = (bodies[1], attmodes[1]) # Rod has two rolls, for a and b points rolla, rollb = get2Rolls() d = Dynamics.RodDynamic(name, att0, rolla, att1, rollb, self.symbols) aliasify("l", d.l) t = aliasify("thetaa", d.thetaa) title = aliasify("T", d.getTSym()) elif dyn == "spring": assert_bodies("spring", 2) assert_offs("spring", 4) pos = (offs["x1"], offs["y1"], offs["x2"], offs["y2"]) att0 = (bodies[0], attmodes[0]) att1 = (bodies[1], attmodes[1]) # Spring has two rolls, for a and b points rolla, rollb = get2Rolls() d = Dynamics.SpringDynamic(name, att0, rolla, att1, rollb, self.symbols) aliasify("l", d.l) aliasify("d", d.d) aliasify("T", d.getTSym()) t = aliasify("thetaa", d.thetaa) title = aliasify("k", d.k) elif dyn == "dampener": assert_bodies("dampener", 2) assert_offs("dampener", 4) pos = (offs["x1"], offs["y1"], offs["x2"], offs["y2"]) att0 = (bodies[0], attmodes[0]) att1 = (bodies[1], attmodes[1]) # Dampener has two rolls, for a and b points rolla, rollb = get2Rolls() d = Dynamics.DampenerDynamic(name, att0, rolla, att1, rollb, self.symbols) aliasify("l", d.l) aliasify("d", d.d) aliasify("T", d.getTSym()) t = aliasify("thetaa", d.thetaa) title = aliasify("b", d.b) elif dyn == "torque": assert_bodies("torque", 1) assert_offs("torque", 2) flipped = int(props.get("direction", 1)) flipped = flipped != 0 pos = (offs["x1"], offs["y1"]) # Angular dynamics have no rolls get0Rolls() d = Dynamics.TorqueDynamic(name, obj, flipped, self.symbols) title = aliasify("k", d.k) elif dyn == "angularspring": assert_bodies("angularspring", 1) assert_offs("angularspring", 2) pos = (offs["x1"], offs["y1"]) # Angular dynamics have no rolls get0Rolls() d = Dynamics.AngularSpringDynamic(name, obj, self.symbols) title = aliasify("k", d.k) elif dyn == "angulardampener": assert_bodies("angulardampener", 1) assert_offs("angulardampener", 2) pos = (offs["x1"], offs["y1"]) # Angular dynamics have no rolls get0Rolls() d = Dynamics.AngularDampenerDynamic(name, obj, self.symbols) title = aliasify("b", d.b) elif dyn == "belt": assert_bodies("belt", 2) assert_offs("belt", 4) pos = (offs["x1"], offs["y1"], offs["x2"], offs["y2"]) att0 = (bodies[0], attmodes[0]) att1 = (bodies[1], attmodes[1]) # Angular dynamics have no rolls get0Rolls() d = Dynamics.BeltDynamic(name, att0, att1, self.symbols) title = aliasify("b", d.b) else: raise Exception("unknown dynamic type %s" % dyn) # Add dynamic to the list of dynamic in the scene self.scene["dynamics"].append(d) # Add dynamic to the collection of dynamics of each body for body in bodies: self.scene["attachments"][body["$.name"]].append(d) # Draw the dynamic self.printer.print_dynamic(name, dyn, pos, title, props) # Draw the angle of the dynamic, if specified if showangles == "1" or showangles == True: self.printer.print_angle(name, t)