From d090ccfcabf936e42a0a707d45f8db89deb4de75 Mon Sep 17 00:00:00 2001 From: Mark Voltov Date: Tue, 23 May 2023 15:48:20 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=BE=D0=BD=D0=B0?= =?UTF-8?q?=D0=BB=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=B0=20=D1=81=D0=BF=D0=B5=D1=86=D0=B8=D1=84=D0=B8=D0=BA=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cg/freecad/Frames/AuxObjCreation.py | 286 ++++++++++++++++++++++++++++ cg/freecad/Frames/BoMList.py | 77 -------- cg/freecad/Frames/Frames.py | 6 +- cg/freecad/Frames/box.py | 0 4 files changed, 291 insertions(+), 78 deletions(-) create mode 100644 cg/freecad/Frames/AuxObjCreation.py create mode 100644 cg/freecad/Frames/box.py diff --git a/cg/freecad/Frames/AuxObjCreation.py b/cg/freecad/Frames/AuxObjCreation.py new file mode 100644 index 0000000..4db00e4 --- /dev/null +++ b/cg/freecad/Frames/AuxObjCreation.py @@ -0,0 +1,286 @@ + + + + " + #Создаем объект, к которому привязываем вспомогательную информацию: + 1. Выбираем элемент в модели: + 1.1. Поверхность - можем создать призматический объект. Соответствует точке захвата, рабочей зоне, опорной поверхности, поверхности базирования + 1.1.1 Выбираем тип объкта, который нам нужно построить. + 1.1.2 В зависимости от выбора, предлагается указать объект для ориентации осей. + 1.1.3 Указать размеры зоны построения. Для захвата соответствует габаритам пальца, для рабочей зоны - координатам. Полуавтоматическое (ручное???) создание эскиза? + 1.1.4 Для захвата выбираем вытягивание объекта на нужную длину до параллельной поверхности + 1.1.5 - Результат - построенный параллелограмм с размерами и привязкой к моделям. Его мы экспортируем в json через существующий функционал + + 1.2. Цилиндрическая поверхность - осесимметричный объект. Захват двухпальцевый, трехпальцевый, четырехпальцевый, цилиндрическая зона установки, отверстия сопряжения + 1.2.1 Выбираем тип объекта + 1.2.2. Выбираем ориентацию главной оси. //Потенциально, мы можем захватить цилиндрический объект в любой ориентации, нужно ли добавлять конкретное указание? + видимо, только если геометрия обязывает нас придерживаться ее (напр. не дает поставить 4 палец) + указание требуется, если есть фиксаторы, опорные площадки или что-то иное, что приводит к однозначному позиционированию + 1.2.3. Вытягиваем зону до привязки. Пальцы ставим как цилиндрический массив( нужно ли??) + 1.2.4 Результат - цилиндрическая зона с радиусом, ориентациями осей. + 2. К размеченным объектам необходимо привязать метаданные, содержащие связи с конкретными моделями. STEP-файл захвата, step-файл входной детали и/или выходной. + 2.1 Нужно ли привязывать захват? Да, но в некоем обобщенном виде. Позиция захвата - характеристика способа воздействия, а не объекта. + 2.2 Для станков входы и выходы необходимы. + 2.3 + " + + + #!/usr/bin/env python3 +# coding: utf-8 +# +# LGPL +# Copyright HUBERT Zoltán +# +# newDatumCmd.py + + +import os + +from PySide import QtGui, QtCore +import FreeCADGui as Gui +import FreeCAD as App +from FreeCAD import Console as FCC + +import Asm4_libs as Asm4 + + + + +""" + +-----------------------------------------------+ + | a class to create all Datum objects | + +-----------------------------------------------+ +""" +class newDatum: + "My tool object" + def __init__(self, datumName): + self.datumName = datumName + # recognised containers (not the same as Asm4.containerTypes !) + self.containers = [ 'App::Part', 'PartDesign::Body', 'App::DocumentObjectGroup'] + if self.datumName == 'Point': + self.datumType = 'PartDesign::Point' + self.menutext = "New Point" + self.tooltip = "Create a new Datum Point in a Part" + self.icon = os.path.join( Asm4.iconPath , 'Asm4_Point.svg') + self.datumColor = (0.00,0.00,0.00) + self.datumAlpha = [] + elif self.datumName == 'Axis': + self.datumType = 'PartDesign::Line' + self.menutext = "New Axis" + self.tooltip = "Create a new Datum Axis in a Part" + self.icon = os.path.join( Asm4.iconPath , 'Asm4_Axis.svg') + self.datumColor = (0.00,0.00,0.50) + self.datumAlpha = [] + elif self.datumName == 'Plane': + self.datumType = 'PartDesign::Plane' + self.menutext = "New Plane" + self.tooltip = "Create a new Datum Plane in a Part" + self.icon = os.path.join( Asm4.iconPath , 'Asm4_Plane.svg') + self.datumColor = (0.50,0.50,0.50) + self.datumAlpha = 80 + elif self.datumName == 'LCS': + self.datumType = 'PartDesign::CoordinateSystem' + self.menutext = "New Coordinate System" + self.tooltip = "Create a new Coordinate System in a Part" + self.icon = os.path.join( Asm4.iconPath , 'Asm4_CoordinateSystem.svg') + self.datumColor = [] + self.datumAlpha = [] + elif self.datumName == 'Sketch': + self.datumType = 'Sketcher::SketchObject' + self.menutext = "New Sketch" + self.tooltip = "Create a new Sketch in a Part" + self.icon = os.path.join( Asm4.iconPath , 'Asm4_Sketch.svg') + self.datumColor = [] + self.datumAlpha = [] + + + def GetResources(self): + return {"MenuText": self.menutext, + "ToolTip": self.tooltip, + "Pixmap" : self.icon } + + + def IsActive(self): + if App.ActiveDocument: + # is something correct selected ? + if self.checkSelection(): + return(True) + return(False) + + + def checkSelection(self): + # if something is selected ... + if Gui.Selection.getSelection(): + selectedObj = Gui.Selection.getSelection()[0] + # ... and it's an App::Part or an datum object + selType = selectedObj.TypeId + if selType in self.containers or selType in Asm4.datumTypes or selType=='Sketcher::SketchObject': + return(selectedObj) + # or of nothing is selected ... + elif Asm4.getAssembly(): + # ... but there is as assembly: + return Asm4.getAssembly() + # if we're here it's because we didn't find a good reason to not be here + return None + + + + """ + +-----------------------------------------------+ + | the real stuff | + +-----------------------------------------------+ + """ + def Activated(self): + # check that we have somewhere to put our stuff + selectedObj = self.checkSelection() + # default name increments the datum type's end numeral + proposedName = Asm4.nextInstance( self.datumName, startAtOne=True ) + + parentContainer = None + # check whether we have selected a container + if selectedObj.TypeId in self.containers: + parentContainer = selectedObj + # if a datum object is selected + elif selectedObj.TypeId in Asm4.datumTypes or selectedObj.TypeId=='Sketcher::SketchObject': + # see whether it's in a container + parent = selectedObj.getParentGeoFeatureGroup() + if parent.TypeId in self.containers: + parentContainer = parent + # if there is an assembly + elif Asm4.getAssembly(): + parentContainer = Asm4.getAssembly() + # something went wrong + else: + Asm4.warningBox("I can't create a "+self.datumType+" with the current selections") + + # check whether there is already a similar datum, and increment the instance number + # instanceNum = 1 + #while App.ActiveDocument.getObject( self.datumName+'_'+str(instanceNum) ): + # instanceNum += 1 + #datumName = self.datumName+'_'+str(instanceNum) + if parentContainer: + # input dialog to ask the user the name of the Sketch: + #proposedName = Asm4.nextInstance( self.datumName + '_' + selectedObj.Label, startAtOne=True ) + text,ok = QtGui.QInputDialog.getText(None,'Create new '+self.datumName, + 'Enter '+self.datumName+' name :'+' '*40, text = proposedName) + if ok and text: + # App.activeDocument().getObject('Model').newObject( 'Sketcher::SketchObject', text ) + createdDatum = App.ActiveDocument.addObject( self.datumType, text ) + parentContainer.addObject( createdDatum ) + createdDatum.Label = text + # automatic resizing of datum Plane sucks, so we set it to manual + if self.datumType=='PartDesign::Plane': + createdDatum.ResizeMode = 'Manual' + createdDatum.Length = 100 + createdDatum.Width = 100 + elif self.datumType=='PartDesign::Line': + createdDatum.ResizeMode = 'Manual' + createdDatum.Length = 200 + # if color or transparency is specified for this datum type + if self.datumColor: + Gui.ActiveDocument.getObject(createdDatum.Name).ShapeColor = self.datumColor + if self.datumAlpha: + Gui.ActiveDocument.getObject(createdDatum.Name).Transparency = self.datumAlpha + # highlight the created datum object + Gui.Selection.clearSelection() + Gui.Selection.addSelection( App.ActiveDocument.Name, parentContainer.Name, createdDatum.Name+'.' ) + Gui.runCommand('Part_EditAttachment') + + + +""" + +-----------------------------------------------+ + | a class to create an LCS on a hole | + +-----------------------------------------------+ +""" +class newHole: + def GetResources(self): + return {"MenuText": "New Hole Axis", + "ToolTip": "Create a Datum Axis attached to a hole", + "Pixmap" : os.path.join( Asm4.iconPath , 'Asm4_Hole.svg') + } + + def IsActive(self): + selection = self.getSelectedEdges() + if selection is None: + return False + else: + return True + + + """ + +-----------------------------------------------+ + | the real stuff | + +-----------------------------------------------+ + """ + def getSelectedEdges(self): + # check that we have selected only circular edges + selection = None + parent = None + edges = [] + # 1 selection means a single parent + if App.ActiveDocument and len(Gui.Selection.getSelection()) == 1: + parent = Gui.Selection.getSelection()[0] + # parse all sub-elemets of the selection + for i in range(len(Gui.Selection.getSelectionEx()[0].SubObjects)): + edgeObj = Gui.Selection.getSelectionEx()[0].SubObjects[i] + edgeName = Gui.Selection.getSelectionEx()[0].SubElementNames[i] + # if the edge is circular + if Asm4.isCircle(edgeObj): + edges.append( [edgeObj,edgeName] ) + # if we found circular edges + if len(edges) > 0: + selection = ( parent, edges ) + return selection + + + def Activated(self): + ( selectedObj, edges ) = self.getSelectedEdges() + for i in range(len(edges)): + edgeObj = edges[i][0] + edgeName = edges[i][1] + parentPart = selectedObj.getParentGeoFeatureGroup() + # we can create a datum only in a container + if parentPart: + parentDoc = parentPart.Document + # if the solid having the edge is indeed in an App::Part + if parentPart and (parentPart.TypeId=='App::Part' or parentPart.TypeId=='PartDesign::Body'): + # check whether there is already a similar datum, and increment the instance number + instanceNum = 1 + while parentDoc.getObject( 'HoleAxis_'+str(instanceNum) ): + instanceNum += 1 + axis = parentPart.newObject('PartDesign::Line','HoleAxis_'+str(instanceNum)) + axis.Support = [( selectedObj, (edgeName,) )] + axis.MapMode = 'AxisOfCurvature' + axis.MapReversed = False + axis.ResizeMode = 'Manual' + axis.Length = edgeObj.BoundBox.DiagonalLength + axis.ViewObject.ShapeColor = (0.0,0.0,1.0) + axis.ViewObject.Transparency = 50 + axis.recompute() + parentPart.recompute() + # + else: + FCC.PrintMessage('Datum objects can only be created inside Part or Body containers') + + + +""" + +-----------------------------------------------+ + | add the commands to the workbench | + +-----------------------------------------------+ +""" +Gui.addCommand( 'Asm4_newPoint', newDatum('Point') ) +Gui.addCommand( 'Asm4_newAxis', newDatum('Axis') ) +Gui.addCommand( 'Asm4_newPlane', newDatum('Plane') ) +Gui.addCommand( 'Asm4_newLCS', newDatum('LCS') ) +Gui.addCommand( 'Asm4_newSketch',newDatum('Sketch')) +Gui.addCommand( 'Asm4_newHole', newHole() ) + +# defines the drop-down button for Datum objects +createDatumList = [ 'Asm4_newLCS', + 'Asm4_newPlane', + 'Asm4_newAxis', + 'Asm4_newPoint', + 'Asm4_newHole' ] +Gui.addCommand( 'Asm4_createDatum', Asm4.dropDownCmd( createDatumList, 'Create Datum Object')) diff --git a/cg/freecad/Frames/BoMList.py b/cg/freecad/Frames/BoMList.py index 8dfe212..fef31eb 100644 --- a/cg/freecad/Frames/BoMList.py +++ b/cg/freecad/Frames/BoMList.py @@ -108,80 +108,3 @@ def run_BoM_list(): sortedParts = uniquePartsSort(labelParts) countedParts = countForUniques(sortedParts) fillInBoMList(sheet, countedParts) - - -# def printETACounter(partLabel): - - - - -# import os -# import requests -# import time - -# import FreeCAD -# from FreeCAD import Base - -# def export_to_stl(doc, filename): -# mesh = doc.getObjectsByType("Mesh")[0] -# mesh.exportStl(filename) - -# def upload_to_octoprint(file_path, api_key, octoprint_url): -# headers = { -# "X-Api-Key": api_key -# } -# files = { -# "file": open(file_path, "rb") -# } -# response = requests.post(octoprint_url + "/api/files/local", headers=headers, files=files) -# if response.status_code == 201: -# print("Файл успешно загружен в OctoPrint.") -# return response.json()["name"] -# else: -# print("Ошибка при загрузке файла в OctoPrint:", response.text) -# return None - -# def get_print_duration(file_name, api_key, octoprint_url): -# headers = { -# "X-Api-Key": api_key -# } -# response = requests.get(octoprint_url + "/api/files/local/" + file_name, headers=headers) -# if response.status_code == 200: -# return response.json()["gcodeAnalysis"]["estimatedPrintTime"] -# else: -# print("Ошибка при получении информации о файле из OctoPrint:", response.text) -# return None - -# # Путь к документу FreeCAD -# doc_path = "/path/to/your/file.FCStd" - -# # Путь для сохранения STL-файла -# stl_path = "/path/to/your/output.stl" - -# # Настройки OctoPrint -# octoprint_api_key = "your_octoprint_api_key" -# octoprint_url = "http://localhost:5000" - -# # Открываем документ FreeCAD -# doc = FreeCAD.open(doc_path) - -# # Экспортируем модель в STL-файл -# export_to_stl(doc, stl_path) -# print("STL-файл успешно создан.") - -# # Загружаем STL-файл в OctoPrint -# uploaded_file_name = upload_to_octoprint(stl_path, octoprint_api_key, octoprint_url) -# if uploaded_file_name is not None: -# # Получаем информацию о длительности печати -# print_duration = get_print_duration(uploaded_file_name, octoprint_api_key, octoprint_url) -# if print_duration is not None: -# print("Оценочная длительность печати: {} секунд.".format(print_duration)) -# else: -# print("Не удалось получить информацию о длительности печати.") -# else: -# print("Загрузка файла в OctoPrint не удалась.") - -# # Закрываем документ FreeCAD -# FreeCAD.closeDocument(doc) - - diff --git a/cg/freecad/Frames/Frames.py b/cg/freecad/Frames/Frames.py index 107da60..dda4886 100644 --- a/cg/freecad/Frames/Frames.py +++ b/cg/freecad/Frames/Frames.py @@ -323,7 +323,11 @@ Tools.spawnClassCommand("FrameCommand", "MenuText": "Make a free frame", "ToolTip": "Make a freestanding reference frame."}) - +Tools.spawnClassCommand("ASM4StructureParsing", + RobossemblerFreeCadExportScenario().call, + {"Pixmap": str(os.path.join(icondir, "assembly4.svg")), + "MenuText": "Make a ASM4 parsing", + "ToolTip": "Make a ASM4 1"}) Tools.spawnClassCommand("SelectedPartFrameCommand", makeSelectedPartFrames, {"Pixmap": str(os.path.join(icondir, "partframe.svg")), diff --git a/cg/freecad/Frames/box.py b/cg/freecad/Frames/box.py new file mode 100644 index 0000000..e69de29