import salome, geompy, math

cylinderLength = 1
cylinderRadius = 0.2
areaThreshold = 4
tolerance = 1e-4

####### THE SCRIPT BEGINS FURTHER ########

# Quickly define a custom "addToStudy" function

def addToStudyAll( array , name ):
	
	i = 0
	
	for element in array:
		
		geompy.addToStudy( element , name + "_" + str(i) )
		i += 1
	

#-

# Define the "vector-vector transformation" function

def VectorTransformation( shape , sourceVector , targetVector ):
	
	# Get the shapes
	
	if isinstance(shape,str):
		
		shapeName=shape
		
		shape=salome.myStudy.FindObjectByName(shapeName,"GEOM")[0].GetObject()
	
	if isinstance(sourceVector,str):
		
		sourceVectorName=sourceVector
		
		sourceVector=salome.myStudy.FindObjectByName(sourceVectorName,"GEOM")[0].GetObject()
		
	
	if isinstance(targetVector,str):
		
		targetVectorName=targetVector
		
		targetVector=salome.myStudy.FindObjectByName(targetVectorName,"GEOM")[0].GetObject()
		
	
	#-
	
	# Get the vector vertexes
	
	sourceVectorVertexes = geompy.SubShapeAll( sourceVector , geompy.ShapeType["VERTEX"] )
	targetVectorVertexes = geompy.SubShapeAll( targetVector , geompy.ShapeType["VERTEX"] )

	#-
	
	# Translate the shape and source vector
	
	shape = geompy.MakeTranslationTwoPoints( shape , sourceVectorVertexes[0] , targetVectorVertexes[0] )
	
	sourceVector = geompy.MakeTranslationTwoPoints( sourceVector , sourceVectorVertexes[0] , targetVectorVertexes[0] )

	#-
	
	# Get the vector components
	
	sourceVectorBoundingBox = geompy.BoundingBox( sourceVector )
	
	sourceVectorComponents = [
	geompy.PointCoordinates( sourceVectorVertexes[1] )[0] - geompy.PointCoordinates( sourceVectorVertexes[0] )[0] ,
	geompy.PointCoordinates( sourceVectorVertexes[1] )[1] - geompy.PointCoordinates( sourceVectorVertexes[0] )[1] ,
	geompy.PointCoordinates( sourceVectorVertexes[1] )[2] - geompy.PointCoordinates( sourceVectorVertexes[0] )[2]
	]
	
	targetVectorBoundingBox = geompy.BoundingBox( targetVector )
	
	targetVectorComponents = [
	geompy.PointCoordinates( targetVectorVertexes[1] )[0] - geompy.PointCoordinates( targetVectorVertexes[0] )[0] ,
	geompy.PointCoordinates( targetVectorVertexes[1] )[1] - geompy.PointCoordinates( targetVectorVertexes[0] )[1] ,
	geompy.PointCoordinates( targetVectorVertexes[1] )[2] - geompy.PointCoordinates( targetVectorVertexes[0] )[2]
	]
	
	#-
	
	# Calculate the rotation axis components
	
	rotationAxisComponents = [
	sourceVectorComponents[1]*targetVectorComponents[2] - sourceVectorComponents[2]*targetVectorComponents[1] ,
	sourceVectorComponents[2]*targetVectorComponents[0] - sourceVectorComponents[0]*targetVectorComponents[2] ,
	sourceVectorComponents[0]*targetVectorComponents[1] - sourceVectorComponents[1]*targetVectorComponents[0]
	]
	
	#-
	
	# Create the rotation axis
	
	rotationAxis = geompy.MakeVectorDXDYDZ( rotationAxisComponents[0] , rotationAxisComponents[1] , rotationAxisComponents[2] )
	
	originVertex = geompy.MakeVertex( 0 , 0 , 0 )
	
	rotationAxis = geompy.MakeTranslationTwoPoints( rotationAxis , originVertex , targetVectorVertexes[0] )
	
	#-
	
	# Get the rotation angle
	
	rotationAngle = geompy.GetAngle( sourceVector , targetVector )
	
	#-
	
	# Rotate the shape
	
	transformedShape = geompy.MakeRotation( shape , rotationAxis , rotationAngle * math.pi / 180 )
	
	#-
	
	return transformedShape
	

#-

####### START OF THE SCRIPT ########

# Create the vertexes

vertexes = []

vertexes.append( geompy.MakeVertex( -1.414 , 0.7071 , 0.000 ))
vertexes.append( geompy.MakeVertex( -1.414 , 0.000 , 0.7071 ))
vertexes.append( geompy.MakeVertex( -1.414 , -0.7071 , 0.000 ))
vertexes.append( geompy.MakeVertex( -1.414 , 0.000 , -0.7071 ))
vertexes.append( geompy.MakeVertex( 1.414 , 0.7071 , 0.000 ))
vertexes.append( geompy.MakeVertex( 1.414 , 0.000 , 0.7071 ))
vertexes.append( geompy.MakeVertex( 1.414 , -0.7071 , 0.000 ))
vertexes.append( geompy.MakeVertex( 1.414 , 0.000 , -0.7071 ))
vertexes.append( geompy.MakeVertex( 0.7071 , -1.414 , 0.000 ))
vertexes.append( geompy.MakeVertex( 0.000 , -1.414 , 0.7071 ))
vertexes.append( geompy.MakeVertex( -0.7071 , -1.414 , 0.000 ))
vertexes.append( geompy.MakeVertex( 0.000 , -1.414 , -0.7071 ))
vertexes.append( geompy.MakeVertex( 0.7071 , 1.414 , 0.000 ))
vertexes.append( geompy.MakeVertex( 0.000 , 1.414 , 0.7071 ))
vertexes.append( geompy.MakeVertex( -0.7071 , 1.414 , 0.000 ))
vertexes.append( geompy.MakeVertex( 0.000 , 1.414 , -0.7071 ))
vertexes.append( geompy.MakeVertex( 0.7071 , 0.000 , -1.414 ))
vertexes.append( geompy.MakeVertex( 0.000 , 0.7071 , -1.414 ))
vertexes.append( geompy.MakeVertex( -0.7071 , 0.000 , -1.414 ))
vertexes.append( geompy.MakeVertex( 0.000 , -0.7071 , -1.414 ))
vertexes.append( geompy.MakeVertex( 0.7071 , 0.000 , 1.414 ))
vertexes.append( geompy.MakeVertex( 0.000 , 0.7071 , 1.414 ))
vertexes.append( geompy.MakeVertex( -0.7071 , 0.000 , 1.414 ))
vertexes.append( geompy.MakeVertex( 0.000 , -0.7071 , 1.414 ))

#addToStudyAll( Vertexes , "Vertex" )

#-

# Create the target vectors

vectors = []

for i in range( len( vertexes ) / 4 ):
	
	i *= 4
	
	vectors.append( geompy.MakeVector( vertexes[i] , vertexes[i+1] ) )
	vectors.append( geompy.MakeVector( vertexes[i+1] , vertexes[i+2] ) )
	vectors.append( geompy.MakeVector( vertexes[i+2] , vertexes[i+3] ) )
	vectors.append( geompy.MakeVector( vertexes[i+3] , vertexes[i] ) )
	

firstVertexIDs = [ 1,5,9,13,3,7,11,15,2,8,4,14 ]
secondVertexIDs = [ 22,20,23,21,18,16,19,17,10,6,12,0 ]

for i in range( len( firstVertexIDs ) ):
	
	vectors.append( geompy.MakeVector( vertexes[ firstVertexIDs[i] ] , vertexes[ secondVertexIDs[i] ] ) )
	

#addToStudyAll( vectors , "vector" )

#-

# Create the cylinder to copy and its vector

sourceCylinder = geompy.MakeCylinderRH( cylinderRadius , cylinderLength )
sourceCylinder = geompy.SubShape( sourceCylinder , geompy.ShapeType["FACE"] , [1] )

sourceVector = geompy.MakeVectorDXDYDZ( 0 , 0 , cylinderLength)

#geompy.addToStudy( sourceCylinder , "sourceCylinder" )
#geompy.addToStudy( sourceVector , "sourceVector" )

#-

# Copy the cylinder

cylinders = []

for vector in vectors:
	
	cylinder = VectorTransformation( sourceCylinder , sourceVector , vector )
	cylinder = geompy.LimitTolerance( cylinder, tolerance )# <--- HERE IS THE KEY ;)
	
	cylinders.append( cylinder )
	

#addToStudyAll( cylinders , "cylinder" )

#-

# Partition the cylinders

partition = geompy.MakePartition( cylinders , [] )

#geompy.addToStudy( partition , "partition" )

#-

# Sort out the faces to keep

explodedFaces = geompy.SubShapeAll( partition , geompy.ShapeType["FACE"] )

keptFaces = []

for face in explodedFaces:
	
	area = geompy.BasicProperties( face )[0]
	
	if area > areaThreshold:
		
		keptFaces.append( face )
		
	

#addToStudyAll( keptFaces , "keptFace" )

#-

# Create the shell

shell = geompy.MakeShell( keptFaces )

#geompy.addToStudy( shell , "shell" )

#-

# Get the shell's hole wires

holeWires = geompy.GetFreeBoundary( shell )[1]

#addToStudyAll( holeWires , "holeWire" )

#-

# Get the hole edges

holeEdges = []

for holeWire in holeWires:
	
	holeWireEdges = geompy.SubShapeAll( holeWire , geompy.ShapeType["EDGE"] )
	
	for holeWireEdge in holeWireEdges:
		
		holeEdges.append( holeWireEdge )
		
	

#addToStudyAll( holeEdges , "holeEdges" )

#-

# Get the edge IDs

holeEdgeIDs = []

for holeEdge in holeEdges:
	
	holeEdgeIDs.append( geompy.GetSubShapeID( shell , holeEdge ) )
	

#print holeEdgeIDs

#-

# Close the holes

closedShell = geompy.SuppressHoles( shell, holeEdgeIDs )

#geompy.addToStudy( closedShell , "closedShell" )

#-

# Create the solid

solid = geompy.MakeSolid( [ closedShell ] )

gg = salome.ImportComponentGUI( "GEOM" )
id = geompy.addToStudy( solid , "kelvin structure" )
gg.createAndDisplayGO( id )

#-

####### END OF THE SCRIPT ########

if salome.sg.hasDesktop():
 salome.sg.updateObjBrowser(1)

