diff --git a/cg/freecad/Frames/MetaObj.py b/cg/freecad/Frames/MetaObj.py new file mode 100644 index 0000000..e69de29 diff --git a/cg/freecad/Frames/img/qXX7sBMbsvA.jpg b/cg/freecad/Frames/img/qXX7sBMbsvA.jpg new file mode 100644 index 0000000..17a6b46 Binary files /dev/null and b/cg/freecad/Frames/img/qXX7sBMbsvA.jpg differ diff --git a/cg/freecad/Frames/newDatumCmd.py b/cg/freecad/Frames/newDatumCmd.py new file mode 100644 index 0000000..d1f2930 --- /dev/null +++ b/cg/freecad/Frames/newDatumCmd.py @@ -0,0 +1,259 @@ +#!/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/Модуль технологической подготовки.md b/cg/freecad/Frames/Модуль технологической подготовки.md new file mode 100644 index 0000000..4ae744f --- /dev/null +++ b/cg/freecad/Frames/Модуль технологической подготовки.md @@ -0,0 +1,27 @@ + + +# Модуль технологической подготовки + +На вход: - step-модель описываемого оборудования. + +1. Описание имеющихся сущностей: + - Мы можем создать описание действий со станком и его состояниями для связи с окружающим миром нужен некий обобщенный объект + его свойством будет возможность воздействовать на состояния, но сам он будет любым. Думаю, нужно описать сами рычаги, а не того, кто будет их нажимать. + + - Описать объекты можно созданием зон вокруг них и/или созданием призрака геометрии оборудования (может быть сложно и избыточно). + - Для этого возможно создать параллелепипед/цилиндр, сопоставимый по габаритам с рассматриваемой зоной. С помощью инструментов верстака Part создается объект, имеющий желаемое название (Станок, рабочая зона, etc). Эта зона с помощью отношений parent привязана к геометрии станка. + +2. Описание действий + - Создается папка actions, в которую сохраняются создаваемые действия + - Интерфейс создания действий аналогичен интерфейсу задания других сущностей. Через него мы задаем ссылки на существующие действия и элементы и указываем их тип: триггеры, рабочие органы, конечные состояния, начальные состояния. Указываем их статус (выбор "да/нет") + - Указываем ссылки на привязываемую к этим действиям геометрию. (катушки, статоры, расходники и тд) Для этого их геометрия должна быть импортирована в модель. Ссылка будет указывать на конкретный импортированный файл. Если существует идентификатор детали, можно ссылаться на него. + +3. Задание состояний и переменных + - Переменные задаются средствами параметризации FreeCAD, инструменты для этого можно взять из ASM4, используя функционал переменных (Variables) и панели конфигураций. + - Для состояний переменных аналогично создается (в ASM4 уже имеется при создании модели) отдельная директория. + +4. Результатом описания будет модель, имеющая дерево объектов, в свойствах которых мы имеем всю необходимую информацию. Геометрические характеристики мы сохраняем как json и отправляем в среды, работающие с геометрией и физикой. Действия и геометрия подставляются в шаблон pddl в соответствующие абзацы. + +Пример размеченной модели: + +![Разметка](img/qXX7sBMbsvA.jpg) \ No newline at end of file