import FreeCADGui, FreeCAD import numpy as np import femmesh.meshtools import FemGui import ObjectsFem locations = [] locationsub = [] objnames=[] dicti = {} #Variables num=0 # Number of nearest neigbours to be found Slope = 1000000.000000 # Contact stiffness Friction = 0.300000 # Friction Scale = 1 # Scale def find_index_of_nearest(array, idx,num ): xpoint=array[idx,0] ypoint=array[idx,1] zpoint=array[idx,2] distance = [] for i in range(array.shape[0]): distance.append((array[i,0]-xpoint)**2 + (array[i,1]-ypoint)**2+ (array[i,2]-zpoint)**2) idxmin = np.argpartition(np.array(distance), num) idxmin=np.array(idxmin[0:num]) idxmin=np.delete(idxmin,np.where(idxmin==idx)) return idxmin def get_all_close_surfaces(array, num): store = [] for i in range(array.shape[0]): store.append(find_index_of_nearest(array,i,num)) return store def addcontactobjects(array,geom): idxfaces=[] iidx=0 idxi=0 for i in array: for j in i: FreeCAD.activeDocument().addObject("Fem::ConstraintContact","FemConstraintContact") idxfaces=np.append(idxfaces,[iidx,j]) iidx+=1 idxfaces=idxfaces.reshape(int(len(idxfaces)/2),2) #print(idxfaces.shape) for obj in FreeCAD.ActiveDocument.Objects: if (obj.isDerivedFrom('Fem::ConstraintContact')): objName = obj.Name #print(objName) obj.Slope = Slope obj.Friction = Friction obj.Scale = Scale face1='Face'+str(idxfaces[idxi,0]+1) #print(face1) face2='Face'+str(idxfaces[idxi,1]+1) #print(face2) obj.References = [(geom,face1), (geom,face2)] idxi+=1 def get_same_surfaces(mainarray,rowsub): indx=0 for row in mainarray: if np.array_equal(row, rowsub): #print("Got it",row,rowsub,indx) idxr=indx indx+=1 return idxr def multidelete(values,todelete): todelete=np.array(todelete) shift=np.triu((todelete>=todelete[:,None]),1).sum(0) return np.delete(values,todelete+shift) def remove_same_sol_face(array,locidx): rownew=[] newmat=[] #indx=0 for i in range(array.shape[0]): solnum=locidx[i] toremove=np.array(np.where(locidx == solnum)[0]) row=np.array(array[i,:]) delistidx=[] for i in toremove: rownew = np.array(np.where(row==i)[0] ) if len(rownew) >= 1: delistidx=np.append(delistidx,rownew[0]) delistidx=np.sort(delistidx)[::-1] newrow=multidelete(row,delistidx) newmat.append(newrow) #print(newmat) return newmat try: for obj in FreeCAD.ActiveDocument.Objects: # seach all objects in document objName = obj.Name objLabel = obj.Label try: if obj.Shape.Faces: # is a face then print( objLabel, objName, len(obj.Shape.Faces), " face(s)") FreeCADGui.Selection.addSelection(FreeCAD.ActiveDocument.getObject(obj.Name)) # select the object with face if 'Compound' in objName: print('Getting vector list for nearest neighbours contact form Compound \n ', objName) objcomp=obj for face in range(len(obj.Shape.Faces)): # list the face(s) of object # print(face) surfaceloc=np.array(obj.Shape.Faces[face].CenterOfMass) # center point locations.append(surfaceloc) # print(surfaceloc) else: print("No object found to apply contact ",objName) locationsub = [] if len(obj.Shape.Faces) > num: num = len(obj.Shape.Faces) for face in range(len(obj.Shape.Faces)): # list the face(s) of object #print(face) surfaceloc=np.array(obj.Shape.Faces[face].CenterOfMass) # center point locationsub.append(surfaceloc) name= objName+'coords' dicti[str(name)] = np.array(locationsub) except Exception: print("Not Shape") except Exception: print("Not object") locations = np.array(locations) num=num+3 #select at least 3 more faces tahn biggest subobject has results = np.array(get_all_close_surfaces(locations,num)) #np.save("resultmat.npy",results) #print(results) #now subobjects idx=0 locsub=np.zeros(len(locations)) for key,val in dicti.items(): for row in val: index=get_same_surfaces(locations,row) locsub[index]=idx idx+=1 uniqueres=remove_same_sol_face(results,locsub) addcontactobjects(uniqueres,objcomp)