def _test_file( self, testFile_basename, solution = None ): testFile = os.path.join( test_assembly_path, testFile_basename + '.fcstd' ) debugPrint(1, testFile_basename ) stats.n_attempted += 1 #if testFile == 'tests/testAssembly11-Pipe_assembly.fcstd': # print('Skipping known fail') # continue doc = FreeCAD.open(testFile) t_start_solver = time.time() constraintSystem = solveConstraints( doc, solver_name = 'dof_reduction_solver', use_cache = self.use_cache ) if solution: self.check_solution( constraintSystem, solution ) stats.t_solver += time.time() - t_start_solver if self.use_cache: debugPrint(1,'\n\n') X_org = constraintSystem.variableManager.X t_start_cache = time.time() #cache.debugMode = 1 constraintSystem = solveConstraints( doc, solver_name = 'dof_reduction_solver', use_cache = self.use_cache ) self.assertTrue( numpy.allclose( X_org , constraintSystem.variableManager.X ), 'Cache solution differs from originial solution: %s != %s' % ( X_org , constraintSystem.variableManager.X ) ) #cache.debugMode = 0 stats.t_cache += time.time() - t_start_cache constraintSystem.update() stats.n_solved += 1 debugPrint(1,'\n\n\n')
def _test_file( self, testFile_basename, solution = None ): testFile = os.path.join( test_assembly_path, testFile_basename + '.fcstd' ) debugPrint(1, testFile_basename ) stats.n_attempted += 1 #if testFile == 'tests/testAssembly11-Pipe_assembly.fcstd': # print('Skipping known fail') # continue doc = FreeCAD.open(testFile) t_start_solver = time.time() constraintSystem = solveConstraints( doc, solver_name = 'dof_reduction_solver', use_cache = self.use_cache, showFailureErrorDialog=False ) if solution: self.check_solution( constraintSystem, solution ) stats.t_solver += time.time() - t_start_solver if self.use_cache: debugPrint(1,'\n\n') X_org = constraintSystem.variableManager.X t_start_cache = time.time() #cache.debugMode = 1 constraintSystem = solveConstraints( doc, solver_name = 'dof_reduction_solver', use_cache = self.use_cache ) self.assertTrue( numpy.allclose( X_org , constraintSystem.variableManager.X ), 'Cache solution differs from originial solution: %s != %s' % ( X_org , constraintSystem.variableManager.X ) ) #cache.debugMode = 0 stats.t_cache += time.time() - t_start_cache constraintSystem.update() stats.n_solved += 1 FreeCAD.closeDocument( doc.Name ) debugPrint(1,'\n\n\n')
def boltSelection(): from assembly2.solvers import solveConstraints doc = FreeCAD.ActiveDocument doc.openTransaction('Bolt Multiple Circular Edges') selection = FreeCADGui.Selection.getSelectionEx() bolt = selection[0].Object bolt_se_name = selection[0].SubElementNames[0] S = [] #edgesToConstrainTo for s in selection[1:]: for se_name in s.SubElementNames: S.append(SelectionExObject(doc, s.Object, se_name)) for s2 in S: newBolt = duplicateImportedPart(bolt) s1 = SelectionExObject(doc, newBolt, bolt_se_name) debugPrint(3, 's1 %s' % [s1, s2]) parseSelection([s1, s2], callSolveConstraints=False, lockRotation=True) solveConstraints(doc) FreeCAD.ActiveDocument.commitTransaction() repair_tree_view()
def boltSelection(): from assembly2.solvers import solveConstraints doc = FreeCAD.ActiveDocument doc.openTransaction('Bolt Multiple Circular Edges') selection = FreeCADGui.Selection.getSelectionEx() bolt = selection[0].Object bolt_se_name = selection[0].SubElementNames[0] S = [] #edgesToConstrainTo for s in selection[1:]: for se_name in s.SubElementNames: S.append( SelectionExObject(doc, s.Object, se_name) ) for s2 in S: newBolt = duplicateImportedPart(bolt) s1 = SelectionExObject(doc, newBolt, bolt_se_name) debugPrint(3,'s1 %s' % [s1, s2]) parseSelection( [s1, s2 ], callSolveConstraints= False, lockRotation = True ) solveConstraints( doc ) FreeCAD.ActiveDocument.commitTransaction() repair_tree_view()
def _test_file( self, testFile_basename, solution = None ): testFile = os.path.join( test_assembly_path, testFile_basename + '.fcstd' ) debugPrint(1, testFile_basename ) stats.n_attempted += 1 #if testFile == 'tests/testAssembly11-Pipe_assembly.fcstd': # print('Skipping known fail') # continue doc = FreeCAD.open(testFile) t_start_solver = time.time() xOpt = solveConstraints( doc, solver_name = 'newton_solver_slsqp', use_cache = self.use_cache, showFailureErrorDialog=False ) if solution: self.check_solution( xOpt, solution ) stats.t_solver += time.time() - t_start_solver assert not self.use_cache if not xOpt is None: stats.n_solved += 1 FreeCAD.closeDocument( doc.Name ) debugPrint(1,'\n\n\n') return xOpt
def Activated(self): #disable proxies solving the system as their objects are updated doc_assembly = FreeCAD.ActiveDocument solve_assembly_constraints = False YesToAll_clicked = False for obj in doc_assembly.Objects: if hasattr(obj, 'sourceFile'): if not hasattr( obj, 'timeLastImport'): obj.addProperty("App::PropertyFloat", "timeLastImport","importPart") #should default to zero which will force update. obj.setEditorMode("timeLastImport",1) if not os.path.exists( obj.sourceFile ) and path_rel_to_abs( obj.sourceFile ) is None: debugPrint( 3, '%s.sourceFile %s is missing, attempting to repair it' % (obj.Name, obj.sourceFile) ) replacement = None aFolder, aFilename = posixpath.split( doc_assembly.FileName ) sParts = path_split( posixpath, obj.sourceFile) debugPrint( 3, ' obj.sourceFile parts %s' % sParts ) replacement = None previousRejects = [] while replacement == None and aFilename != '': for i in reversed(range(len(sParts))): newFn = aFolder for j in range(i,len(sParts)): newFn = posixpath.join( newFn,sParts[j] ) debugPrint( 4, ' checking %s' % newFn ) if os.path.exists( newFn ) and not newFn in previousRejects : if YesToAll_clicked: replacement = newFn break reply = QtGui.QMessageBox.question( QtGui.QApplication.activeWindow(), "%s source file not found" % obj.Name, "Unable to find\n %s \nUse \n %s\n instead?" % (obj.sourceFile, newFn) , QtGui.QMessageBox.Yes | QtGui.QMessageBox.YesToAll | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) if reply == QtGui.QMessageBox.Yes: replacement = newFn break if reply == QtGui.QMessageBox.YesToAll: replacement = newFn YesToAll_clicked = True break else: previousRejects.append( newFn ) aFolder, aFilename = posixpath.split( aFolder ) if replacement != None: obj.sourceFile = replacement else: QtGui.QMessageBox.critical( QtGui.QApplication.activeWindow(), "Source file not found", "update of %s aborted!\nUnable to find %s" % (obj.Name, obj.sourceFile) ) obj.timeLastImport = 0 #force update if users repairs link if path_rel_to_abs( obj.sourceFile ) is not None: absolutePath = path_rel_to_abs( obj.sourceFile ) if os.path.getmtime( absolutePath ) > obj.timeLastImport: importPart( absolutePath, obj.Name, doc_assembly ) solve_assembly_constraints = True if os.path.exists( obj.sourceFile ): if os.path.getmtime( obj.sourceFile ) > obj.timeLastImport: importPart( obj.sourceFile, obj.Name, doc_assembly ) solve_assembly_constraints = True if solve_assembly_constraints: solveConstraints( doc_assembly ) # constraint mirror house keeping for obj in doc_assembly.Objects: #for adding creating mirrored constraints in old files if 'ConstraintInfo' in obj.Content: if doc_assembly.getObject( obj.Object1 ) == None or doc_assembly.getObject( obj.Object2 ) == None: debugPrint(2, 'removing %s which refers to non-existent objects' % obj.Name) doc_assembly.removeObject( obj.Name ) #required for FreeCAD 0.15 which does not support the on-delete method if group_constraints_under_parts(): if not hasattr( obj.ViewObject.Proxy, 'mirror_name'): if isinstance( doc_assembly.getObject( obj.Object1 ).Proxy, Proxy_importPart) \ or isinstance( doc_assembly.getObject( obj.Object2 ).Proxy, Proxy_importPart): debugPrint(2, 'creating mirror of %s' % obj.Name) doc_assembly.getObject( obj.Object2 ).touch() obj.ViewObject.Proxy.mirror_name = create_constraint_mirror( obj, obj.ViewObject.Proxy.iconPath ) elif 'ConstraintNfo' in obj.Content: #constraint mirror if doc_assembly.getObject( obj.ViewObject.Proxy.constraintObj_name ) == None: debugPrint(2, 'removing %s which mirrors/links to a non-existent constraint' % obj.Name) doc_assembly.removeObject( obj.Name ) #clean up for FreeCAD 0.15 which does not support the on-delete method elif not group_constraints_under_parts(): debugPrint(2, 'removing %s since group_constraints_under_parts=False' % obj.Name) delattr( doc_assembly.getObject( obj.ViewObject.Proxy.constraintObj_name ), 'mirror_name' ) doc_assembly.removeObject( obj.Name ) elif hasattr(obj,'Proxy') and isinstance( obj.Proxy, Proxy_importPart) and not isinstance( obj.ViewObject.Proxy, ImportedPartViewProviderProxy): obj.ViewObject.Proxy = ImportedPartViewProviderProxy() debugPrint(2, '%s.ViewObject.Proxy = ImportedPartViewProviderProxy()'%obj.Name) doc_assembly.recompute()
def Activated(self): from assembly2.solvers import solveConstraints constraintSystem = solveConstraints(FreeCAD.ActiveDocument) self.taskPanel = AnimateDegreesOfFreedomTaskPanel(constraintSystem) FreeCADGui.Control.showDialog(self.taskPanel)
def generate_animation(self): preferences = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Assembly2") org_auto_solve = preferences.GetBool( 'autoSolveConstraintAttributesChanged', True) preferences.SetBool('autoSolveConstraintAttributesChanged', False) try: if hasattr(self, 'constraintAnimator'): self.constraintAnimator.stop() from assembly2.solvers import solveConstraints P = {} for p in animation_parameters: if hasattr(p, 'getValue'): p.add_property_to_freecad_object() P[p.name] = p.getValue() debugPrint(3, 'generate_animation parms %s' % P) constraint_to_animate = self.taskDialog.constraint_to_animate self.original_expressions = constraint_to_animate.ExpressionEngine #[('angle', '12')] self.X = [] if not hasattr(constraint_to_animate, 'a'): constraint_to_animate.addProperty({ 'angle_between_planes': 'App::PropertyAngle', 'plane': 'App::PropertyDistance', 'circularEdge': 'App::PropertyDistance' }[constraint_to_animate.Type], 'a', "animationParameters") constraint_to_animate.setEditorMode('a', 2) attr_to_animate = { 'angle_between_planes': 'angle', 'plane': 'offset', 'circularEdge': 'offset' }[constraint_to_animate.Type] attr_org_value = getattr(constraint_to_animate, attr_to_animate) constraint_to_animate.setExpression(attr_to_animate, P['animation_exp']) moduleVars['progressDialog'] = QtGui.QProgressDialog( "Generating Animation", "Cancel", 0, P['a_n']) p = moduleVars['progressDialog'] p.setWindowModality(QtCore.Qt.WindowModal) p.forceShow() A = numpy.linspace(P['a_0'], P['a_1'], P['a_n']) for count, a in enumerate(A): if not p.wasCanceled(): p.setLabelText('solving %i/%i' % (count + 1, P['a_n'])) p.setValue(count) debugPrint(3, 'solving constraint system for a=%1.1f' % a) constraint_to_animate.a = a FreeCAD.ActiveDocument.recompute( ) #update other expersions constraint_sys = solveConstraints(FreeCAD.ActiveDocument) self.X.append(constraint_sys.variableManager.X.copy()) #variableManager.updateFreeCADValues( constraintSystem.variableManager.X ) set_exp_to_none = True for ent in self.original_expressions: if ent[0] == attr_to_animate: constraint_to_animate.setExpression( attr_to_animate, ent[1]) set_exp_to_none = False if set_exp_to_none: constraint_to_animate.setExpression(attr_to_animate, None) setattr(constraint_to_animate, attr_to_animate, attr_org_value) if not p.wasCanceled(): p.setValue( P['a_n']) #hopefully this will close the progress dialog if P['interp_method'] == 'none': pass elif P['interp_method'] == 'linear': self.X = linear_interp(self.X, A, P['n_interp']) elif P['interp_method'] == 'Cubic_Hermite_spline': self.X = spline_interp(self.X, A, P['n_interp']) else: raise NotImplemented self.playStopButton.setEnabled(True) self.constraintAnimator = ConstraintAnimator( self.X, constraint_sys.variableManager) if P['play_after_generate']: self.playStopButton_clicked() except: FreeCAD.Console.PrintError(traceback.format_exc()) preferences.SetBool('autoSolveConstraintAttributesChanged', org_auto_solve) debugPrint(3, 'done generating constraint animation')
def reject(self): #or more correctly close, given the button settings if hasattr(self.form, 'constraintAnimator'): self.form.constraintAnimator.stop() from assembly2.solvers import solveConstraints solveConstraints(FreeCAD.ActiveDocument) FreeCADGui.Control.closeDialog()
def callSolveConstraints(self): from assembly2.solvers import solveConstraints solveConstraints( FreeCAD.ActiveDocument )
def generate_animation( self ): preferences = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Assembly2") org_auto_solve = preferences.GetBool('autoSolveConstraintAttributesChanged', True) preferences.SetBool('autoSolveConstraintAttributesChanged', False) try: if hasattr( self, 'constraintAnimator' ): self.constraintAnimator.stop() from assembly2.solvers import solveConstraints P = {} for p in animation_parameters: if hasattr(p,'getValue'): p.add_property_to_freecad_object() P[p.name] = p.getValue() debugPrint(3, 'generate_animation parms %s' % P ) constraint_to_animate = self.taskDialog.constraint_to_animate self.original_expressions = constraint_to_animate.ExpressionEngine #[('angle', '12')] self.X = [] if not hasattr(constraint_to_animate, 'a'): constraint_to_animate.addProperty( {'angle_between_planes':'App::PropertyAngle', 'plane':'App::PropertyDistance', 'circularEdge':'App::PropertyDistance'}[ constraint_to_animate.Type ], 'a', "animationParameters" ) constraint_to_animate.setEditorMode( 'a', 2) attr_to_animate = {'angle_between_planes':'angle', 'plane':'offset', 'circularEdge':'offset'}[ constraint_to_animate.Type ] attr_org_value = getattr( constraint_to_animate, attr_to_animate) constraint_to_animate.setExpression( attr_to_animate, P['animation_exp'] ) moduleVars['progressDialog'] = QtGui.QProgressDialog("Generating Animation", "Cancel", 0, P['a_n']) p = moduleVars['progressDialog'] p.setWindowModality(QtCore.Qt.WindowModal) p.forceShow() A = numpy.linspace(P['a_0'],P['a_1'],P['a_n']) for count, a in enumerate(A): if not p.wasCanceled(): p.setLabelText( 'solving %i/%i' % (count+1, P['a_n']) ) p.setValue(count) debugPrint(3, 'solving constraint system for a=%1.1f' % a ) constraint_to_animate.a = a FreeCAD.ActiveDocument.recompute() #update other expersions constraint_sys = solveConstraints( FreeCAD.ActiveDocument ) self.X.append( constraint_sys.variableManager.X.copy() ) #variableManager.updateFreeCADValues( constraintSystem.variableManager.X ) set_exp_to_none = True for ent in self.original_expressions: if ent[0] == attr_to_animate: constraint_to_animate.setExpression( attr_to_animate,ent[1] ) set_exp_to_none = False if set_exp_to_none: constraint_to_animate.setExpression( attr_to_animate, None ) setattr( constraint_to_animate, attr_to_animate, attr_org_value ) if not p.wasCanceled(): p.setValue(P['a_n']) #hopefully this will close the progress dialog if P['interp_method'] == 'none': pass elif P['interp_method'] == 'linear': self.X = linear_interp( self.X, A , P['n_interp'] ) elif P['interp_method'] == 'Cubic_Hermite_spline': self.X = spline_interp( self.X, A , P['n_interp'] ) else: raise NotImplemented self.playStopButton.setEnabled( True ) self.constraintAnimator = ConstraintAnimator( self.X, constraint_sys.variableManager) if P['play_after_generate']: self.playStopButton_clicked() except: FreeCAD.Console.PrintError( traceback.format_exc() ) preferences.SetBool('autoSolveConstraintAttributesChanged',org_auto_solve) debugPrint(3, 'done generating constraint animation' )
def reject(self): #or more correctly close, given the button settings if hasattr( self.form, 'constraintAnimator' ): self.form.constraintAnimator.stop() from assembly2.solvers import solveConstraints solveConstraints( FreeCAD.ActiveDocument ) FreeCADGui.Control.closeDialog()