User:Renatorivo

From FreeCAD Documentation
Revision as of 22:56, 15 February 2015 by Renatorivo (talk | contribs) (Macro Half Hull)
#
#
#			Half Hull
#
#
################################

import FreeCAD
from FreeCAD import Base, Draft
import Part, PartGui, sys, math, collections
from collections import OrderedDict
from os.path import expanduser		# default input directory
from PySide import QtGui, QtCore

# UI Class definitions

class ConfigParams:
	"""carrier for the user selection parameters"""
	def __init__(self):
		self.result				= None
		self.cb1a				= None
		self.cb1b				= None
		self.cb1c				= None
		self.cb2a				= None
		self.cb2b				= None
		self.cb2c				= None
		self.cb3a				= None
		self.cb3b				= None
		self.cb3c				= None
		self.cb4a				= None
		self.rb4b				= None
		self.rb5b				= None
		self.skipAtBow			= None
		self.skipAtStern		= None
		self.deckWidth			= None
		self.deckThrow			= None
		self.coachhouseRise		= None
		self.coachhouseIncline	= None
		self.documentFileName	= None

class GetConfigParams(QtGui.QDialog):
	""""""
	def __init__(self):
		super(GetConfigParams, self).__init__()
		self.initUI()
	def initUI(self):
		self.configParams			= ConfigParams()
		# set default return value
		self.configParams.result 	= userCancelled
		# set default values
		skipAtBowDefault			= str(2)
		skipAtSternDefault			= str(2)
		deckWidthDefault			= str(50)
		deckThrowDefault			= str(2)
		coachhouseRiseDefault		= str(50)
		coachhouseInclineDefault	= str(8)
		# field descriptors
		self.promptLbl = QtGui.QLabel("Please Choose Options:", self)
		self.promptLbl.move(20, 20)
		# checkboxes - define first so  signals can be set up
		self.cb1a = QtGui.QCheckBox("Starboard half-hull", self)
		self.cb1b = QtGui.QCheckBox("Mounting plaque", self)
		self.cb1c = QtGui.QCheckBox("Allow space for keel", self)
		self.cb2a = QtGui.QCheckBox("Port half-hull", self)
		self.cb2b = QtGui.QCheckBox("Mounting plaque", self)
		self.cb2c = QtGui.QCheckBox("Allow space for keel", self)
		self.cb3a = QtGui.QCheckBox("Complete hull", self)
		self.cb3b = QtGui.QCheckBox("Bottle for complete hull", self)
		self.cb3c = QtGui.QCheckBox("Allow space for keel", self)
		self.rb4b = QtGui.QRadioButton("Bulkheads for flush deck",self)
		self.rb5b = QtGui.QRadioButton("Bulkheads for coachhouse",self)
		#
		self.cb1a.clicked.connect(self.onCb1a)
		self.cb1a.toggle() # set default value
		self.cb1c.setEnabled(False)
		#self.cb1a.stateChanged.connect(self.onCb1a)
		self.cb1a.move(20,50)
		#
		self.cb1b.clicked.connect(self.onCb1b)
		self.cb1b.move(250,50)
		#
		self.cb1c.clicked.connect(self.onCb1c)
		self.cb1c.move(450,50)
		#
		self.cb2a.clicked.connect(self.onCb2a)
		self.cb2b.setEnabled(False)
		self.cb2c.setEnabled(False)
		self.cb2a.move(20,80)
		#
		self.cb2b.clicked.connect(self.onCb2b)
		self.cb2b.move(250,80)
		#
		self.cb2c.clicked.connect(self.onCb2c)
		self.cb2c.move(450,80)
		#
		self.cb3a.clicked.connect(self.onCb3a)
		self.cb3b.setEnabled(False)
		self.cb3c.setEnabled(False)
		self.cb3a.move(20,110)
		#
		self.cb3b.clicked.connect(self.onCb3b)
		self.cb3b.move(250,110)
		#
		self.cb3c.clicked.connect(self.onCb3c)
		self.cb3c.move(450,110)
		#
		self.cb4a = QtGui.QCheckBox("Bulkheads for complete hull", self)
		self.cb4a.clicked.connect(self.onCb4a)
		self.rb4b.setEnabled(False)
		self.rb5b.setEnabled(False)
		#self.hideCoachhouseFields(True) # grey out coachhouse fields
		self.cb4a.move(20,140)
		# radio buttons
		self.rb4b.move(250,140)
		self.rb4b.clicked.connect(self.onRb4b)
		#
		self.rb5b.move(250,170)
		self.rb5b.clicked.connect(self.onRb5b)
		#
		self.skipAtBowLabel = QtGui.QLabel("Cross-sections to skip at bow:", self)
		self.skipAtBowLabel.move(270, 200)
		self.skipAtBow = 0
		#
		self.skipAtSternLabel = QtGui.QLabel("Cross-sections to skip at stern:", self)
		self.skipAtSternLabel.move(270, 230)
		self.skipAtStern = 0
		#
		self.deckWidthLabel = QtGui.QLabel("Deck Width:", self)
		self.deckWidthLabel.move(270, 260)
		self.deckWidth = QtGui.QLineEdit(self)
		self.deckWidth.setInputMask("999")
		self.deckWidth.setText(deckWidthDefault)
		self.deckWidth.setFixedWidth(35)
		self.deckWidth.move(493, 260)
		#
		self.deckThrowLabel = QtGui.QLabel("Deck throw:", self)
		self.deckThrowLabel.move(270, 290)
		self.deckThrow = QtGui.QLineEdit(self)
		self.deckThrow.setInputMask("999")
		self.deckThrow.setText(deckThrowDefault)
		self.deckThrow.setFixedWidth(35)
		self.deckThrow.move(493, 290)
		#
		self.coachhouseRiseLabel = QtGui.QLabel("Coachhouse Rise:", self)
		self.coachhouseRiseLabel.move(270, 320)
		self.coachhouseRise = QtGui.QLineEdit(self)
		self.coachhouseRise.setInputMask("999")
		self.coachhouseRise.setText(coachhouseRiseDefault)
		self.coachhouseRise.setFixedWidth(35)
		self.coachhouseRise.move(493, 320)
		#
		self.coachhouseInclineLabel = QtGui.QLabel("Coachhouse Incline:", self)
		self.coachhouseInclineLabel.move(270, 350)
		self.coachhouseIncline = QtGui.QLineEdit(self)
		self.coachhouseIncline.setInputMask("999")
		self.coachhouseIncline.setText(coachhouseInclineDefault)
		self.coachhouseIncline.setFixedWidth(35)
		self.coachhouseIncline.move(493, 350)
		# set up lists for pop-ups
		self.popupItemsB = OrderedDict([("2",""),("3",""),("4",""),("5",""),("6",""),("7",""),("8",""),("9",""),("10","")])
		self.popupItemsS = OrderedDict([("1",""),("2",""),("3",""),("4",""),("5",""),("6",""),("7",""),("8",""),("9",""),("10","")])
		# set up pop-up menu of bulkheads to skip bulkheads at bow
		self.skipAtBowPop = QtGui.QComboBox(self)
		self.skipAtBowPop.addItems(self.popupItemsB.keys())
		self.skipAtBowPop.setCurrentIndex(self.popupItemsB.keys().index(skipAtBowDefault))
		self.skipAtBow = skipAtBowDefault
		self.skipAtBowPop.move(490, 200)
		self.skipAtBowPop.activated[str].connect(self.onSkipBowActivated)
		# set up pop-up menu of bulkheads to skip bulkheads at stern
		self.skipAtSternPop = QtGui.QComboBox(self)
		self.skipAtSternPop.addItems(self.popupItemsS.keys())
		self.skipAtSternPop.setCurrentIndex(self.popupItemsS.keys().index(skipAtSternDefault))
		self.skipAtStern = skipAtSternDefault
		self.skipAtSternPop.move(490, 230)
		self.skipAtSternPop.activated[str].connect(self.onSkipSternActivated)
		# cancel button
		cancelButton = QtGui.QPushButton('Cancel', self)
		cancelButton.clicked.connect(self.onCancel)
		cancelButton.move(260, 390)
		# last used button
		lastFileButton = QtGui.QPushButton('Re-use last file', self)
		lastFileButton.clicked.connect(self.onLastFile)
		lastFileButton.move(345, 390)
		# OK button
		sfButton = QtGui.QPushButton('Select File', self)
		sfButton.clicked.connect(self.onSf)
		sfButton.move(480, 390)
		# define window		xLoc,yLoc,xDim,yDim
		self.setGeometry(	250, 250, 630, 445)
		self.setWindowTitle("Macro Configuration")
		self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
		self.disableCoachhouseFields(True) # grey out coachhouse fields
		self.show()
		#
	def onCb1a(self):
		if self.cb1a.isChecked():
			self.cb1b.setEnabled(True)
		else:
			self.cb1b.setEnabled(False)
			self.cb1b.setChecked(False)
			self.cb1c.setEnabled(False)
			self.cb1c.setChecked(False)
	def onCb1b(self):
		if self.cb1b.isChecked():
			self.cb1c.setEnabled(True)
		else:
			self.cb1c.setEnabled(False)
			self.cb1c.setChecked(False)
	def onCb1c(self):
		pass
	def onCb2a(self):
		if self.cb2a.isChecked():
			self.cb2b.setEnabled(True)
		else:
			self.cb2b.setEnabled(False)
			self.cb2b.setChecked(False)
			self.cb2c.setEnabled(False)
			self.cb2c.setChecked(False)
	def onCb2b(self):
		if self.cb2b.isChecked():
			self.cb2c.setEnabled(True)
		else:
			self.cb2c.setEnabled(False)
			self.cb2c.setChecked(False)
	def onCb2c(self):
		pass
	def onCb3a(self):
		if self.cb3a.isChecked():
			self.cb3b.setEnabled(True)
		else:
			self.cb3b.setEnabled(False)
			self.cb3b.setChecked(False)
			self.cb3c.setEnabled(False)
			self.cb3c.setChecked(False)
	def onCb3b(self):
		if self.cb3b.isChecked():
			self.cb3c.setEnabled(True)
		else:
			self.cb3c.setEnabled(False)
			self.cb3c.setChecked(False)
	def onCb3c(self):
		pass
	def onCb4a(self):
		if self.cb4a.isChecked():
			self.rb4b.setEnabled(True)
			self.rb4b.setChecked(True)
			self.rb5b.setEnabled(True)
			self.rb5b.setChecked(False)
		else:
			self.rb4b.setChecked(False)
			self.rb4b.setEnabled(False)
			self.rb5b.setChecked(False)
			self.rb5b.setEnabled(False)
			self.disableCoachhouseFields(True)
	def onRb4b(self):
		if self.rb4b.isChecked():
			self.disableCoachhouseFields(True)
		else:
			self.disableCoachhouseFields(False)
	def onRb5b(self):
		if self.rb5b.isChecked():
			self.disableCoachhouseFields(False)
		else:
			self.disableCoachhouseFields(True)
	def onSkipBowActivated(self, text):
		self.skipAtBow = text
	def onSkipSternActivated(self, text):
		self.skipAtStern = text
	def disableCoachhouseFields(self, aFlag):
		# enable or disable coachhouse parameter fields
		if aFlag:
			self.skipAtBowLabel.setEnabled(False)
			self.skipAtBowPop.setEnabled(False)
			self.skipAtSternLabel.setEnabled(False)
			self.skipAtSternPop.setEnabled(False)
			self.deckWidthLabel.setEnabled(False)
			self.deckWidth.setEnabled(False)
			self.deckThrowLabel.setEnabled(False)
			self.deckThrow.setEnabled(False)
			self.coachhouseRiseLabel.setEnabled(False)
			self.coachhouseRise.setEnabled(False)
			self.coachhouseInclineLabel.setEnabled(False)
			self.coachhouseIncline.setEnabled(False)
		else:
			self.skipAtBowLabel.setEnabled(True)
			self.skipAtBowPop.setEnabled(True)
			self.skipAtSternLabel.setEnabled(True)
			self.skipAtSternPop.setEnabled(True)
			self.deckWidthLabel.setEnabled(True)
			self.deckWidth.setEnabled(True)
			self.deckThrowLabel.setEnabled(True)
			self.deckThrow.setEnabled(True)
			self.coachhouseRiseLabel.setEnabled(True)
			self.coachhouseRise.setEnabled(True)
			self.coachhouseInclineLabel.setEnabled(True)
			self.coachhouseIncline.setEnabled(True)
	def onCancel(self):
		self.configParams.result			= userCancelled
		self.close()
	def transferConfigParams(self):
		self.configParams.cb1a				= self.cb1a.isChecked()
		self.configParams.cb1b				= self.cb1b.isChecked()
		self.configParams.cb1c				= self.cb1c.isChecked()
		self.configParams.cb2a				= self.cb2a.isChecked()
		self.configParams.cb2b				= self.cb2b.isChecked()
		self.configParams.cb2c				= self.cb2c.isChecked()
		self.configParams.cb3a				= self.cb3a.isChecked()
		self.configParams.cb3b				= self.cb3b.isChecked()
		self.configParams.cb3c				= self.cb3c.isChecked()
		self.configParams.cb4a				= self.cb4a.isChecked()
		self.configParams.rb5b				= self.rb5b.isChecked()
		self.configParams.skipAtBow			= self.skipAtBow
		self.configParams.skipAtStern		= self.skipAtStern
		self.configParams.deckWidth			= self.deckWidth
		self.configParams.deckThrow			= self.deckThrow
		self.configParams.coachhouseRise	= self.coachhouseRise
		self.configParams.coachhouseIncline	= self.coachhouseIncline
	def onLastFile(self):
		self.configParams.result			= userLastFile
		self.transferConfigParams()
		self.close()
	def onSf(self):
		self.configParams.result			= userOK
		self.transferConfigParams()
		self.close()

# Class definitions

class HullCrossSection:
	"Holder of information pertaining to a cross section profile"
	#persistentInstance = ""
	#import copy
	def __init__(self,aSketch):
		self.sketch =		aSketch
		self.geometryCount = aSketch.GeometryCount
		self.geometryS =	None # geometry for starboard side
		self.geometryP =	None # geometry for port side
		self.geometryC =	None # geometry for complete hull (i.e. both halves as one)
		self.label =		aSketch.Label
		# next 2 lines due to mysterious label morphing routine of FreeCAD
		self.altLabel =		self.label.replace(" ", "_")
		self.altLabel =		self.altLabel.replace("-", "_")
		#
		self.xPos =			0.0 # normalise sketch to axis
		self.yPos =			aSketch.Placement.Base.y
		self.zPos =			aSketch.Placement.Base.z
		self.xMin =			infinity # will hold min X value in Sketch
		self.yMin =			infinity # will hold min Y value in Sketch
		self.xMax =			infinityNegative # will hold max X value in Sketch
		self.yMax =			infinityNegative # will hold max Y value in Sketch
		self.endPoint =		None # will be the 'top' point on the polyline
		self.key =			int(self.yPos)
		self.rotation =		aSketch.Placement.Rotation
		self.rotAngle =		aSketch.Placement.Rotation.Angle
		self.rotAxis =		aSketch.Placement.Rotation.Axis
		self.rotQ =			aSketch.Placement.Rotation.Q
		# following 4 statements seem necessary to pass the Rotation quad-value
		self.rotQ1 =		aSketch.Placement.Rotation.Q[0]
		self.rotQ2 =		aSketch.Placement.Rotation.Q[1]
		self.rotQ3 =		aSketch.Placement.Rotation.Q[2]
		self.rotQ4 =		aSketch.Placement.Rotation.Q[3]
		# set flags for either stemline or transom or suspected transom cross-section
		if eqRotation(self.rotation,yzPlane):
			# if we have the stemline then wait to give it the foremost placement
			FreeCAD.Console.PrintMessage("Stemline identified '" + self.label + "'\n")
			self.stemlineFlag = True
		else:
			self.stemlineFlag = False
		if eqRotation(self.rotation,xyPlane):
			# if we have the transom then wait to give it the aftmost placement
			FreeCAD.Console.PrintMessage("Transom identified '" + self.label + "'\n")
			self.transomFlag = True
		else:
			self.transomFlag = False
		if eqRotation(self.rotation,xzPlane):
			# the most numerous sketches will be the cross-sections, so don't flag it
			self.possibleTransomCS = False
		else:
			# it's not lying in any of the 3 planes so it's either an error
			# or it could be an inclined cross-section for the transom
			# (although there should only be one or none of these)
			# flag it as such and sort it out later once all the other
			# cross-sections are placed
			if not (self.stemlineFlag or self.transomFlag):
				FreeCAD.Console.PrintMessage("Possible Transom cross-section identified '" + self.label + "'\n")
				self.possibleTransomCS = True
		self.defineGeometries() # make S & P & C geometries from the geometry of the supplied Sketch
				
	def defineGeometries(self):
		# the supplied geometry is for the starboard side and is part of the user supplied Sketch
		# - make a direct copy for the starboard half-hull
		# - negate the X coordinates for the Port side
		# - append a negated reversed copy to each starboard piece for the complete hull
		self.geometryS =	list()
		self.geometryP =	list()
		self.geometryC =	list()
		#grab the endPoint which will be used for covering the half-hull model
		epX = max(self.sketch.Geometry[-1].StartPoint.x, self.sketch.Geometry[-1].EndPoint.x)
		epY = self.yPos
		epZ = max(self.sketch.Geometry[-1].StartPoint.y, self.sketch.Geometry[-1].EndPoint.y)
		self.endPoint = Base.Vector(epX,epY,epZ)
		# first pass through segment of sketch is to determine the min and max X & Y values
		for seg in self.sketch.Geometry:
			# determine the minimum X & Y values
			self.xMin = min(self.xMin, seg.StartPoint.x, seg.EndPoint.x)	
			self.yMin = min(self.yMin, seg.StartPoint.y, seg.EndPoint.y)
			self.xMax = max(self.xMax, seg.StartPoint.x, seg.EndPoint.x)	
			self.yMax = max(self.yMax, seg.StartPoint.y, seg.EndPoint.y)
		# second pass is to create the S, P and starboard side of the C geometries
		for seg in self.sketch.Geometry:
			# extract the X,Y,Z for start and end
			segStartX = seg.StartPoint.x
			segStartY = seg.StartPoint.y
			segStartZ = seg.StartPoint.z
			segEndX   = seg.EndPoint.x
			segEndY   = seg.EndPoint.y
			segEndZ   = seg.EndPoint.z
			absMinX   = abs(self.xMin)
			# normalise segments within drawing to X axis if not stemline
			if not self.stemlineFlag:
				if abs(segStartX) == absMinX:
					if 0<absMinX<1:
						segStartX = 0
					elif absMinX >= 1:
						FreeCAD.Console.PrintMessage("Move to Y axis of '" + self.label + "'\n")
						if segStartX<0:
							segStartX = segStartX + absMinX
						elif segEndX>0:
							segStartX = segStartX - absMinX
				if abs(segEndX) == absMinX:
					if 0<absMinX<1:
						segEndX = 0
					elif absMinX >= 1:
						FreeCAD.Console.PrintMessage("Move to Y axis of '" + self.label + "'\n")
						if segEndX<0:
							segEndX = segEndX + absMinX
						elif segEndX>0:
							segEndX = segEndX - absMinX
			# now create starboard, port, complete geometries
			self.geometryS.append(Part.Line(
				Base.Vector(segStartX, segStartY, segStartZ),
				Base.Vector(segEndX, segEndY, segEndZ)))
			if self.stemlineFlag:
				# stemline is on the YZ axis and is common to both half-hulls
				# so don't flip it's X coordinates
				multiplicand = 1
			else:
				multiplicand = -1
			self.geometryP.append(Part.Line(
				Base.Vector(segStartX*multiplicand, segStartY, segStartZ),
				Base.Vector(segEndX*multiplicand, segEndY, segEndZ)))
			# starboard geometry is first half of complete hull geometry
			self.geometryC.append(self.geometryS[-1])
		# third pass is to create the Complete geometry so the segments have
		# constant direction from starboard to port:
		# 1) reverse segment order of starboard side
		# 2 copy port side geometry
		segCnt = len(self.sketch.Geometry)
		completeGeometry = list()
		for i in range(segCnt):
			completeGeometry.append(self.reverseLineDirection(self.geometryS[segCnt-1-i]))	
		for i in range(segCnt):
			completeGeometry.append(self.reverseLineDirection(self.geometryP[i]))	
		self.geometryC = completeGeometry
		
	def reverseLineDirection(self,aLine):
		return Part.Line(aLine.EndPoint, aLine.StartPoint)

# Function definitions

def createBottle(aKeelFlag):
	# create a bottle around the hull
	bottleRadius = 250
	neckRadius = 75
	bottleBottom = -1000
	bottleTop = 400
	neckBottom = 800
	neckTop = 1150
	corkHeight = 100
	# get some dimensions for the plaque based on the size of the hull or half-hull
	minusX = crossSections[-2].yPos * 1.1
	plusX = (crossSections[0].yPos + crossSections[0].yMax) * 1.1
	minusY = 0; plusY = 0
	for cs in crossSections:
		#minusY = max(minusY, abs(cs.yMin))
		plusY = max(plusY, cs.yMax)
	minusY = plusY * -0.75
	plusY = plusY * 1.1
	#print minusX, " ", plusX, " ", minusY, " ", plusY
	
	bs0 = FreeCAD.ActiveDocument.addObject("Part::Vertex","Ring0")
	bs0.Label='Ring0'
	bs0.X=0.00
	bs0.Y=bottleBottom*0.97
	bs0.Z=0.00
	bs0.Placement = Base.Placement(	Base.Vector(0.00,0.00,0.00),
									Base.Rotation(0.00,0.00,0.00,1.00))
	bs0.ViewObject.Visibility=False
	#
	bs1 = FreeCAD.activeDocument().addObject('Sketcher::SketchObject','Ring1')
	bs1.addGeometry(Part.Circle(Base.Vector(0,0,0), Base.Vector(0,0,1), bottleRadius))
	bs1.Placement = FreeCAD.Placement(FreeCAD.Vector(0.0,bottleBottom,0.0),
									FreeCAD.Rotation(-0.707107,0.0,0.0,-0.707107))
	#
	bs2 = FreeCAD.activeDocument().addObject('Sketcher::SketchObject','Ring2')
	bs2.addGeometry(Part.Circle(Base.Vector(0,0,0), Base.Vector(0,0,1), bottleRadius))
	bs2.Placement = FreeCAD.Placement(FreeCAD.Vector(0.0,bottleTop,0.0),
									FreeCAD.Rotation(-0.707107,0.0,0.0,-0.707107))
	#
	bs3 = FreeCAD.activeDocument().addObject('Sketcher::SketchObject','Ring3')
	bs3.addGeometry(Part.Circle(Base.Vector(0,0,0), Base.Vector(0,0,1), neckRadius))
	bs3.Placement = FreeCAD.Placement(FreeCAD.Vector(0.0,neckBottom,0.0),
									FreeCAD.Rotation(-0.707107,0.0,0.0,-0.707107))
	#
	bs4 = FreeCAD.activeDocument().addObject('Sketcher::SketchObject','Ring4')
	bs4.addGeometry(Part.Circle(Base.Vector(0,0,0), Base.Vector(0,0,1), neckRadius))
	bs4.Placement = FreeCAD.Placement(FreeCAD.Vector(0.0,neckTop,0.0),
									FreeCAD.Rotation(-0.707107,0.0,0.0,-0.707107))
	#
	bot0 = FreeCAD.getDocument('hull_complete').addObject('Part::Loft','Loft0')
	bot0.Sections=[bs0, bs1,]
	bot0.Solid=False; bot0.Ruled=False; bot0.Closed=False
	#
	bot1 = FreeCAD.getDocument('hull_complete').addObject('Part::Loft','Loft1')
	bot1.Sections=[bs1, bs2,]
	bot1.Solid=False; bot1.Ruled=False; bot1.Closed=False
	#
	bot2 = FreeCAD.getDocument('hull_complete').addObject('Part::Loft','Loft2')
	bot2.Sections=[bs2, bs3,]
	bot2.Solid=False; bot2.Ruled=False; bot2.Closed=False
	#
	bot3 = FreeCAD.getDocument('hull_complete').addObject('Part::Loft','Loft3')
	bot3.Sections=[bs3,bs4,]
	bot3.Solid=False; bot3.Ruled=False; bot3.Closed=False
	#
	bottle = FreeCAD.activeDocument().addObject("Part::MultiFuse","Bottle")
	bottle.Shapes = [bot0,bot1,bot2,bot3,]
	bot1.ViewObject.Visibility=False
	bot2.ViewObject.Visibility=False
	bot3.ViewObject.Visibility=False
	#bottle.ViewObject.ShapeColor=Gui.ActiveDocument.Loft1.ShapeColor
	bottle.ViewObject.DisplayMode="Shaded"
	bottle.ViewObject.Transparency=80
	bottle.ViewObject.ShapeColor=(0.4, 0.8, 0.5, 0.0)
	FreeCAD.ActiveDocument.recompute()
	#
	cork = FreeCAD.ActiveDocument.addObject("Part::Cylinder","Cylinder")
	cork.Label = "Cork"
	cork.Radius = neckRadius-1
	cork.Height = corkHeight
	cork.Placement = FreeCAD.Placement(	FreeCAD.Vector(0.0,neckTop-(corkHeight/2),0.0),
										FreeCAD.Rotation(FreeCAD.Vector(1,0,0),-90))
	cork.ViewObject.ShapeColor=(0.78, 0.65, 0.35, 0.0)
	cork.ViewObject.DisplayMode = "Shaded"
	#
	FreeCADGui.activeDocument().activeView().viewAxometric()
	FreeCADGui.SendMsgToActiveView("ViewFit")
	FreeCAD.ActiveDocument.recompute()

def createBulkheads(aDictionary):
	userAction = None

	docKey = findOpenDocumentName(outputWorkspaceB)
	print docKey
	if docKey!=None:
		reply = QtGui.QMessageBox.question(None, "",
			"The previous 'Bulkheads' output file is still open, close it",
			QtGui.QMessageBox.Yes