Добавлен функционал генератора спецификаций

This commit is contained in:
Mark Voltov 2023-05-23 15:48:20 +03:00
parent dfb647a3ec
commit bd12df9d85
12 changed files with 998 additions and 18 deletions

View file

@ -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'))

View file

@ -0,0 +1,110 @@
from helper.is_solid import is_object_solid
import FreeCAD as App
import Spreadsheet
def createSpreadsheet():
if App.ActiveDocument.getObject("BoM_List") == None:
sheet = App.activeDocument().addObject('Spreadsheet::Sheet', 'BoM_List')
sheet.set('A1', 'п.п.')
sheet.set('B1', 'Наименование детали')
sheet.set('C1', 'Количество')
else:
sheet = App.ActiveDocument.getObject("BoM_List")
App.ActiveDocument.BoM_List.clear('A1:ZZ16384')
sheet.set('A1', 'п.п.')
sheet.set('B1', 'Наименование детали')
sheet.set('C1', 'Количество')
return (sheet)
class SolidBodiesParcer:
_asmThere = []
def __init__(self) -> None:
if (self._asmThere.__len__() == 0):
self.initParse()
pass
def initParse(self):
for el in App.ActiveDocument.RootObjects:
if (is_object_solid(el) and hasattr(el, 'Group')):
self.getSubPartsLink(el.Group, el.Label)
def getSubPartsLink(self, group, label):
groupLink = {label: []}
for el in group:
if (is_object_solid(el)):
groupLink[label].append(
{'label': el.Label, 'isGroup': hasattr(el, 'Group'), 'solid': el})
for el in groupLink[label]:
if ('isGroup' in el):
if (el['isGroup'] == False):
self._asmThere.append(el['solid'].Label)
if (el['isGroup']):
self.getSubPartsLink(el['solid'].Group, el['label']),
return groupLink
def uniquePartsSort(labelParts):
uniquePartsLabels = {}
for el in labelParts:
for k in labelParts:
if (App.ActiveDocument.getObjectsByLabel(str(el))[0].Shape.isPartner(App.ActiveDocument.getObjectsByLabel(str(k))[0].Shape)):
if uniquePartsLabels.get(el) == None:
uniquePartsLabels[el] = k
sortedParts = {}
for k, v in uniquePartsLabels.items():
if sortedParts.get(v) == None:
sortedParts[v] = [k]
else:
sortedParts[v].append(k)
return sortedParts
def countForUniques(sortedParts):
countedParts = {}
for k in sortedParts:
countedParts[k] = len(sortedParts[k])
return countedParts
def fillInBoMList(sheet, countedParts):
a = 1
for label, count in countedParts.items():
a += 1
b = label
c = count
sheet.set('A' + str(a), str(a-1))
sheet.set('B' + str(a), str(b))
sheet.set('C' + str(a), str(c))
total_count = sum(countedParts.values())
sheet.set('B'+str(a+1), 'Итого')
sheet.set('C' + str(a+1), str(total_count))
def run_BoM_list():
createSpreadsheet()
sheet = App.ActiveDocument.getObject("BoM_List")
labelParts = SolidBodiesParcer()._asmThere
sortedParts = uniquePartsSort(labelParts)
countedParts = countForUniques(sortedParts)
fillInBoMList(sheet, countedParts)

View file

@ -0,0 +1,49 @@
import FreeCAD
import FreeCADGui
from PySide import QtGui, QtCore
class DatumTool:
"""
A tool for creating datums in existing models
"""
def __init__(self):
self.active = False
def activate(self):
self.active = True
FreeCAD.Console.PrintMessage("Datum tool activatedn")
def deactivate(self):
self.active = False
FreeCAD.Console.PrintMessage("Datum tool deactivatedn")
def mousePressEvent(self, event):
if self.active:
# Create a datum at the position of the mouse click
pos = FreeCADGui.ActiveDocument.ActiveView.getCursorPos()
point = FreeCADGui.ActiveDocument.ActiveView.getPoint(pos)
datum = FreeCAD.ActiveDocument.addObject("Part::Datum", "Datum")
datum.Placement.Base = point
datum.ViewObject.ShapeColor = (0.0, 1.0, 0.0) # Set the color of the datum to green
FreeCAD.ActiveDocument.recompute()
class DatumCommand:
"""
A command for activating and deactivating the datum tool
"""
def __init__(self):
self.tool = DatumTool()
def Activated(self):
self.tool.activate()
FreeCADGui.ActiveDocument.ActiveView.addEventCallback("SoMouseButtonEvent", self.tool.mousePressEvent)
def Deactivated(self):
self.tool.deactivate()
FreeCADGui.ActiveDocument.ActiveView.removeEventCallback("SoMouseButtonEvent", self.tool.mousePressEvent)
def GetResources(self):
return {'Pixmap': 'path/to/icon.png', 'MenuText': 'Datum Tool', 'ToolTip': 'Creates datum elements in existing models'}
# Add the command to the Draft Workbench
FreeCADGui.addCommand('DatumCommand', DatumCommand())

View file

@ -11,9 +11,11 @@
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
from BoMList import run_BoM_list
import FreeCAD
import Tools
from scenarios.robossembler_freecad_export_scenario import RobossemblerFreeCadExportScenario
from usecases.asm4parser_usecase import Asm4StructureParseUseCase
if FreeCAD.GuiUp:
import FreeCADGui
@ -298,6 +300,13 @@ def spawnFeatureFrameCreator():
ffpanel = FeatureFramePanel()
FreeCADGui.Control.showDialog(ffpanel)
def BoMGeneration(part):
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython",
"FeatureFrame")
print(obj)
###################################################################
# GUI Related
@ -306,22 +315,26 @@ uidir = os.path.join(FreeCAD.getUserAppDataDir(),
"Mod", __workbenchname__, "UI")
icondir = os.path.join(uidir, "icons")
Tools.spawnClassCommand("FrameCommand",
makeFrame,
{"Pixmap": str(os.path.join(icondir, "frame.svg")),
"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")),
"MenuText": "selected parts frames",
"ToolTip": "Make selected parts frames."})
# Tools.spawnClassCommand("FrameCommand",
# makeFrame,
# {"Pixmap": str(os.path.join(icondir, "frame.svg")),
# "MenuText": "Make a free frame",
# "ToolTip": "Make a freestanding reference frame."})
Tools.spawnClassCommand("BoMGeneration",
run_BoM_list,
{"Pixmap": str(os.path.join(icondir, "BoMList.svg")),
"MenuText": "Generate Bill of Materials",
"ToolTip": "Press the button to create big BoM"})
# Tools.spawnClassCommand("ASM4StructureParsing",
# Asm4StructureParseUseCase().initParse,
# {"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")),
# "MenuText": "selected parts frames",
# "ToolTip": "Make selected parts frames."})
Tools.spawnClassCommand("AllPartFramesCommand",
makeAllPartFrames,

View file

@ -36,10 +36,13 @@ class Frames(Workbench):
"""This function is executed when FreeCAD starts"""
import Frames
self.framecommands = [
"BoMGeneration",
"FrameCommand",
"SelectedPartFrameCommand",
"AllPartFramesCommand",
"FeatureFrameCommand"
"FeatureFrameCommand",
]
self.toolcommands = [
"ExportPlacementAndPropertiesCommand",

View file

@ -0,0 +1,60 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Sheet_addition_test.py
#
# Copyright 2015 Ulrich Brammer <ulrich@Pauline>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#
theDoc = App.newDocument("SheetTest")
App.setActiveDocument("SheetTest")
#App.activeDocument("SheetTest")
p=App.ParamGet("User parameter:BaseApp/Preferences/General")
thePath = p.GetString('FileOpenSavePath')
mySheet = theDoc.addObject('Spreadsheet::Sheet','Spreadsheet')
mySheet.set('A1', '1')
mySheet.set('A2', '2')
theDoc.recompute()
mySheet.set('A3', '=A1+A2')
mySheet.setPosition('A4')
#theDoc.saveAs("/home/ulrich/FreeCAD/Spreadsheet/Sheet_4.fcstd")
theDoc.saveAs(thePath + '/Sheet_5.fcstd')
mySheet.set('A4', '=A3')
theDoc.recompute()
if mySheet.State == ['Invalid']:
print "Invalid Spreadsheet"
else:
print "No error found"
def main():
return 0
if __name__ == '__main__':
main()

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="32px" height="32px" id="svg3085" version="1.1" inkscape:version="0.92.4 (5da689c313, 2019-01-14)" sodipodi:docname="a2p_PartsList.svg">
<defs id="defs3087">
<inkscape:path-effect effect="skeletal" id="path-effect3066" is_visible="true" pattern="M 0,0 0,10 10,5 z" copytype="single_stretched" prop_scale="1" scale_y_rel="false" spacing="0" normal_offset="0" tang_offset="0" prop_units="false" vertical_pattern="false" fuse_tolerance="0"/>
<linearGradient inkscape:collect="always" id="linearGradient7597">
<stop style="stop-color:#000003;stop-opacity:1;" offset="0" id="stop7599"/>
<stop style="stop-color:#000003;stop-opacity:0;" offset="1" id="stop7601"/>
</linearGradient>
<marker inkscape:stockid="Arrow1Lstart" orient="auto" refY="0.0" refX="0.0" id="Arrow1Lstart" style="overflow:visible">
<path id="path3995" d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt" transform="scale(0.8) translate(12.5,0)"/>
</marker>
<marker inkscape:stockid="Arrow1Send" orient="auto" refY="0.0" refX="0.0" id="Arrow1Send" style="overflow:visible;">
<path id="path4010" d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;" transform="scale(0.2) rotate(180) translate(6,0)"/>
</marker>
<marker inkscape:stockid="Arrow1Sstart" orient="auto" refY="0.0" refX="0.0" id="Arrow1Sstart" style="overflow:visible">
<path id="path4007" d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt" transform="scale(0.2) translate(6,0)"/>
</marker>
<marker inkscape:stockid="Arrow2Sstart" orient="auto" refY="0.0" refX="0.0" id="Arrow2Sstart" style="overflow:visible">
<path id="path4025" style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round" d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " transform="scale(0.3) translate(-2.3,0)"/>
</marker>
<marker inkscape:stockid="TriangleOutL" orient="auto" refY="0.0" refX="0.0" id="TriangleOutL" style="overflow:visible">
<path id="path4137" d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt" transform="scale(0.8)"/>
</marker>
<marker inkscape:stockid="DiamondLend" orient="auto" refY="0.0" refX="0.0" id="DiamondLend" style="overflow:visible">
<path id="path4092" d="M 0,-7.0710768 L -7.0710894,0 L 0,7.0710589 L 7.0710462,0 L 0,-7.0710768 z " style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt" transform="scale(0.8) translate(-7,0)"/>
</marker>
<marker inkscape:stockid="DiamondLstart" orient="auto" refY="0.0" refX="0.0" id="DiamondLstart" style="overflow:visible">
<path id="path4083" d="M 0,-7.0710768 L -7.0710894,0 L 0,7.0710589 L 7.0710462,0 L 0,-7.0710768 z " style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt" transform="scale(0.8) translate(7,0)"/>
</marker>
<marker inkscape:stockid="Arrow1Lend" orient="auto" refY="0.0" refX="0.0" id="Arrow1Lend" style="overflow:visible;">
<path id="path3998" d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;" transform="scale(0.8) rotate(180) translate(12.5,0)"/>
</marker>
<linearGradient id="linearGradient3893">
<stop style="stop-color:#ffffff;stop-opacity:1;" offset="0" id="stop3895"/>
<stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop3897"/>
</linearGradient>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient7597" id="linearGradient7603" x1="15.71482" y1="22.299378" x2="34.136209" y2="22.299378" gradientUnits="userSpaceOnUse"/>
</defs>
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="16" inkscape:cx="17.629635" inkscape:cy="8.4343604" inkscape:current-layer="layer1" showgrid="true" inkscape:grid-bbox="true" inkscape:document-units="px" inkscape:window-width="1920" inkscape:window-height="1018" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:window-maximized="1"/>
<metadata id="metadata3090">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<g id="layer1" inkscape:label="Layer 1" inkscape:groupmode="layer">
<rect style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.11415751000000000;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" id="rect3018" width="1.2970899" height="32.02499" x="0.058561768" y="0.011311022"/>
<rect style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.11415751000000000;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" id="rect3018-5" width="1.2970899" height="32.02499" x="30.72147" y="0.021291591"/>
<rect style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.11415751;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" id="rect3018-3" width="1.2970899" height="32.02499" x="-0.026408914" y="-32.054981" transform="matrix(0,1,-1,0,0,0)"/>
<rect style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.11415751;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" id="rect3018-3-6" width="1.2970899" height="32.02499" x="11.354873" y="-31.978708" transform="matrix(0,1,-1,0,0,0)"/>
<rect style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.11415751;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" id="rect3018-3-6-9" width="1.2970899" height="32.02499" x="22.061981" y="-31.934517" transform="matrix(0,1,-1,0,0,0)"/>
<rect style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.11415751;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" id="rect3018-3-6-9-2" width="1.2970899" height="32.02499" x="30.636494" y="-31.934515" transform="matrix(0,1,-1,0,0,0)"/>
<g id="g4617">
<path sodipodi:nodetypes="ccccccccc" inkscape:connector-curvature="0" id="path3369" d="M 1.4229313,27.000257 V 23.442626 H 16.029106 30.63528 v 3.557631 3.557631 H 16.029106 1.4229313 Z" style="fill:#ffffff;fill-opacity:1"/>
<text id="text3100" y="27.713165" x="11.433594" style="font-style:normal;font-weight:bold;line-height:0%;font-family:sans-serif;-inkscape-font-specification:'Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" xml:space="preserve"><tspan style="font-size:8px;line-height:1.25;font-family:sans-serif" y="27.713165" x="11.433594" id="tspan3102" sodipodi:role="line">...</tspan></text>
</g>
<path style="fill:#ffffff;fill-opacity:1" d="m 6.2842904,5.3724349 0,-0.8007207 0.5237353,0 c 0.5882447,0 0.7620882,0.041783 0.9637654,0.2316391 0.2499922,0.2353392 0.2907934,0.7148274 0.086406,1.0154223 C 7.6895473,6.0668098 7.4826438,6.1358185 6.848381,6.1555803 l -0.5640906,0.017575 0,-0.8007208 z" id="path3375" inkscape:connector-curvature="0"/>
<path style="fill:#ffffff;fill-opacity:1" d="M 11.823275,8.4123074 C 11.48911,8.3155617 11.339256,7.8685764 11.550817,7.5996196 11.705969,7.4023768 11.881121,7.3559471 12.470055,7.3559471 l 0.53175,0 -2.48e-4,0.1436311 c -7.16e-4,0.4175365 -0.294436,0.8141335 -0.673669,0.9096255 -0.234672,0.059091 -0.309638,0.059552 -0.504614,0.0031 l 1e-6,0 z" id="path3377" inkscape:connector-curvature="0"/>
<g id="g3754">
<path inkscape:connector-curvature="0" id="path3373" d="M 1.4229313,6.317384 V 1.345539 H 16.029106 30.63528 v 4.971845 4.971845 H 16.029106 1.4229313 Z" style="fill:#ffffff;fill-opacity:1" sodipodi:nodetypes="ccccccccc"/>
<text id="text3013" y="9.2841949" x="4.0273438" style="font-style:normal;font-weight:bold;line-height:0%;font-family:sans-serif;-inkscape-font-specification:'Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" xml:space="preserve"><tspan style="font-size:8px;line-height:1.25;font-family:sans-serif" y="9.2841949" x="4.0273438" id="tspan3015" sodipodi:role="line">Parts</tspan></text>
</g>
<g id="g4612">
<path sodipodi:nodetypes="ccccccccc" inkscape:connector-curvature="0" id="path3371" d="M 1.4229313,17.365927 V 12.747636 H 16.029106 30.63528 v 4.618291 4.618292 H 16.029106 1.4229313 Z" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-opacity:1"/>
<text id="text3017" y="20.221827" x="7.5078125" style="font-style:normal;font-weight:bold;line-height:0%;font-family:sans-serif;-inkscape-font-specification:'Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" xml:space="preserve"><tspan style="font-size:8px;line-height:1.25;font-family:sans-serif" y="20.221827" x="7.5078125" id="tspan3019" sodipodi:role="line">List</tspan></text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.4 KiB

View file

@ -0,0 +1,240 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg5821"
sodipodi:version="0.32"
inkscape:version="1.0 (1.0+r73+1)"
sodipodi:docname="Asm4_Datum.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
inkscape:export-filename="/home/normand/Images/Icônes/PartDesign_Std_Plane_nc1.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs5823">
<linearGradient
inkscape:collect="always"
id="linearGradient6349">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop6351" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop6353" />
</linearGradient>
<linearGradient
id="linearGradient3377">
<stop
style="stop-color:#0019a3;stop-opacity:1;"
offset="0"
id="stop3379" />
<stop
style="stop-color:#0069ff;stop-opacity:1;"
offset="1"
id="stop3381" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="linearGradient3383"
x1="901.1875"
y1="1190.875"
x2="1267.9062"
y2="1190.875"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-1,0,0,1,2199.356,0)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective5829" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient6349"
id="radialGradient6355"
cx="1103.6399"
cy="1424.4465"
fx="1103.6399"
fy="1424.4465"
r="194.40614"
gradientTransform="matrix(-1.4307499,-1.3605156e-7,-1.202713e-8,0.1264801,2674.7488,1244.2826)"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3776"
id="linearGradient3782"
x1="33.052631"
y1="73.676765"
x2="23.483253"
y2="19.131313"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
id="linearGradient3776">
<stop
style="stop-color:#cc0000;stop-opacity:1"
offset="0"
id="stop3778" />
<stop
style="stop-color:#ef2929;stop-opacity:1"
offset="1"
id="stop3780" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8.0773852"
inkscape:cx="50.403398"
inkscape:cy="46.554586"
inkscape:current-layer="g3360-3"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1048"
inkscape:window-x="0"
inkscape:window-y="32"
inkscape:window-maximized="1"
inkscape:snap-bbox="false"
inkscape:snap-nodes="true"
inkscape:snap-global="false"
inkscape:document-rotation="0">
<inkscape:grid
type="xygrid"
id="grid2997"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata5826">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
<dc:creator>
<cc:Agent>
<dc:title>[wmayer]</dc:title>
</cc:Agent>
</dc:creator>
<dc:title>Sketcher_Sketch</dc:title>
<dc:date>2011-10-10</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier>FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_Sketch.svg</dc:identifier>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
<dc:contributor>
<cc:Agent>
<dc:title>[agryson] Alexander Gryson</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3360"
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/draft.png"
inkscape:export-xdpi="3.2478156"
inkscape:export-ydpi="3.2478156"
transform="matrix(0.1367863,0,0,0.1367863,-119.15519,-134.86962)">
<g
id="g3360-3"
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/draft.png"
inkscape:export-xdpi="3.2478156"
inkscape:export-ydpi="3.2478156"
transform="translate(-2.96179e-7,2.9614273e-6)">
<g
transform="matrix(0.86585328,0,0,1.0022331,158.36626,-5.6554462)"
id="g860">
<rect
transform="matrix(0.86410236,0.50331612,-0.8660254,0.5,0,0)"
y="479.03436"
x="1745.9357"
height="266.99686"
width="266.52176"
id="rect3860-36-6"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#c1b7bb;stroke-width:36.8974;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<rect
ry="2.5860298"
transform="matrix(0.8660254,0.5,-0.8660254,0.5,0,0)"
y="487.53268"
x="1749.7632"
height="265.90598"
width="267.47815"
id="rect3860-3-1"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#999999;fill-opacity:1;stroke:#d6d6d6;stroke-width:15.7117;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<g
transform="matrix(1,0,0,-1,15.589571,2441.7923)"
id="g4172">
<rect
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#999999;fill-opacity:0.5;stroke:#403c3d;stroke-width:36.8936;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
id="rect3860-36"
width="266.52176"
height="266.99686"
x="1138.8126"
y="1717.2489"
transform="matrix(0.86793573,-0.49667653,0,1,0,0)" />
<rect
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;stroke:#897e7e;stroke-width:15.7117;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
id="rect3860-3"
width="267.47815"
height="265.90598"
x="1141.3009"
y="1723.0597"
transform="matrix(0.8660254,-0.5,0,1,0,0)"
ry="2.5860298" />
</g>
<g
transform="translate(14.62135,61.744554)"
id="g4162">
<rect
style="fill:#b90720;fill-opacity:1;stroke:#172a04;stroke-width:13.677;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4154"
width="289.10248"
height="22.203979"
x="1130.2279"
y="528.82843"
ry="10.96601"
rx="0"
transform="matrix(0.8660254,0.5,0,1,0,0)" />
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.6 KiB

0
cg/freecad/Frames/box.py Normal file
View file

View file

@ -0,0 +1,17 @@
import FreeCAD as App
def is_object_solid(obj):
"""If obj is solid return True"""
if not isinstance(obj, FreeCAD.DocumentObject):
return False
if not hasattr(obj, 'Shape'):
return False
return obj.Shape.isClosed()
def addProperty():
for obj in App.ActiveDocument().Objects:
if is_object_solid(obj):

View file

@ -0,0 +1,77 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# faculSpread.py
#
# Copyright 2015 ulrich1a
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#
p=App.ParamGet("User parameter:BaseApp/Preferences/General")
thePath = p.GetString('FileOpenSavePath')
theDoc = App.newDocument("SheetTest2")
App.setActiveDocument("SheetTest2")
mySheet = theDoc.addObject('Spreadsheet::Sheet','Spreadsheet')
col = 'A'
mySheet.setColumnWidth(col, 125)
theDoc.recompute()
startRow = 3
for i in range(20):
print "i: ", i
if i == 0:
print "setting start"
mySheet.set(col+str(startRow+i), '1')
#App.activeDocument().recompute()
else:
mySheet.set(col + str(startRow+i), '='+col+str(startRow+i-1)+'*'+str(i))
#App.activeDocument().recompute()
#mySheet.show()
#App.activeDocument().recompute()
mySheet.set('A1', 'This is the very long Titel, which needs more space!')
mySheet.set('A2', '=A1')
# mySheet.setDisplayUnit('A10:A11', 'mm')
theDoc.recompute()
mySheet.setAlias('A1', 'Title')
mySheet.set('D1', '=Title')
theDoc.recompute()
theDoc.saveAs(thePath + '/Sheet_6.fcstd')
mySheet.set('B4','=A4')
mySheet.set('E1', '=D1')
theDoc.recompute()
mySheet.setAlias('A2', 'huhu')
theDoc.recompute()
if mySheet.State == ['Invalid']:
print "Invalid Spreadsheet"
else:
print "No error found"

View file

@ -0,0 +1,53 @@
import FreeCAD as App
class Asm4StructureParseUseCase:
_parts = []
_label = []
def getSubPartsLabel(self, group):
groupLabel = []
for el in group:
if str(el) == '<Part::PartFeature>':
groupLabel.append(el.Label)
return groupLabel
def parseLabel(self, nextGroup, label, level=2, nextGroupParse=0):
if nextGroup.__len__() == nextGroupParse:
return
else:
groupParts = []
for el in nextGroup:
if str(el) == '<App::Link object>':
groupParts.append(el)
for el in groupParts:
if str(el) == '<App::Link object>':
label.append({
"level": level,
"attachedTo": el.AttachedTo.split('#'),
"label": el.Label,
"axis": self.getSubPartsLabel(el.Group)
})
def initParse(self):
model = App.ActiveDocument.RootObjects[1]
self._label.append({
"level": 1,
"attachedTo": "Parent Assembly",
"label": model.Label,
"axis": self.getSubPartsLabel(model.Group)
})
for parent in model.Group:
if str(parent) == '<App::Link object>':
self._label.append({
"level": 1,
"attachedTo": parent.AttachedTo.split('#'),
"label": parent.Label,
"axis": self.getSubPartsLabel(parent.Group)
})
print(self._label)