--COVERT --COincident VERTex data --list of coincident vertices -------------------------------------------------------------------------------------------------------------------------------- --COVERT SUB-STRUCTS -------------------------------------------------------------------------------------------------------------------------------- --struct to represent each coincidence struct COVERT_Match ( position = [0,0,0], objectList = #() --list of each COVERT_Object items ) --struct for each object struct COVERT_Object ( obj, --an object involved in a coincident vertex data list vertList = #{} --coincident vertices ) struct COVERT_List ( public matchList = #(), --array of coincidences tolerance = 0.01, --checking distance for coincident vertices objList = #(), --list of objects involved with coincident vertices private objectEdgeVertList =#(), --working array for processing matchList -------------------------------------------------------------------------------------------------------------------------------- --DATA FUNCTIONS -------------------------------------------------------------------------------------------------------------------------------- --Returns a list of all the objects that have coincident vertices fn GetCOVERT_Objects = ( local objectList = #() for match in this.matchList do ( for thisObj in match.objectList do ( if (findItem objectList thisObj.obj) == 0 then append objectList thisObj.obj ) ) this.objList = objectList ), --function tests if two objects are in proximity fn ProximityTest obj1 obj2 = ( local proximity = false if (obj1.min.x <= obj2.max.x and obj1.min.y <= obj2.max.y and obj1.min.z <= obj2.max.z) then ( if (obj1.max.x >= obj2.min.x and obj1.max.y >= obj2.min.y and obj1.max.z >= obj2.min.z) then ( proximity = true ) ) return proximity ), --function removes entries in the objectEdgeVertList array that are not proximal fn ProximityCull = ( local validNodes = #() for item in this.objectEdgeVertList do ( for comparison in this.objectEdgeVertList where (item != comparison) do ( if (this.ProximityTest item.obj comparison.obj) then ( appendIfUnique validNodes item ) ) ) this.objectEdgeVertList = validNodes ), --Once a coincidence is found, this function adds the object/id to the data fn AppendMatchList position obj1 id1 obj2 id2 = ( --check to see if the coincidence already exists local found = false for match in this.matchList do ( if (distance match.position position < this.tolerance) then ( found = true --append the coincidence with the object/id's this.AppendExistingMatch &match obj1 id1 this.AppendExistingMatch &match obj2 id2 ) ) --if it doesn't exist, create a new match item if (not found) then ( local newCOVERT_Match --if the vertex match is on a single object if (obj1.handle == obj2.handle) then ( local newCOVERT_Object = COVERT_Object obj1 vertList:#{id1, id2} newCOVERT_Match = COVERT_Match position:position objectList:#(newCOVERT_Object) ) else -- the match is on separate objects ( local COVERT_Object1 = COVERT_Object obj:obj1 vertList:#{id1} local COVERT_Object2 = COVERT_Object obj:obj2 vertList:#{id2} newCOVERT_Match = COVERT_Match position:position objectList:#(COVERT_Object1, COVERT_Object2) ) append this.matchList newCOVERT_Match ) ), --if the new coincidence matches with an existing coincidence, this function appends the coincidence item --called exclusively from AppendMatchList fn AppendExistingMatch &match newObj newID = ( local foundObject = false for objItem in match.objectList do ( if (objItem.obj.handle == newObj.handle) then ( --object found, so append the idList local foundVertex = false for id in objItem.vertList do ( if (id == newID) then foundVertex = true --don't need to add as we have already noted this vertex ) if (not foundVertex) then ( append objItem.vertList newID ) foundObject = true ) ) if (not foundObject) then ( --add a new object/id for this position append match.objectList (COVERT_Object obj:newObj vertList:#{newID}) ) ), -------------------------------------------------------------------------------------------------------------------------------- --PUBLIC FUNCTIONS -------------------------------------------------------------------------------------------------------------------------------- public --function to process passed nodes into coincidences in the matchList array --nodes: geometry objects --return: list of COVERT_Match objects fn InitCOVERT_List nodes = ( local objSet = for this in nodes where superClassOf this == GeometryClass collect this clearListener() if (objSet.count > 0) then ( for item in objSet do ( local openEdgeList local edgeVertList local vertPositionList = #() local idPositionList = #() convertToPoly item openEdgeList = polyop.getOpenEdges item edgeVertList = polyop.getVertsUsingEdge item openEdgeList for id in (edgeVertList as array) do append idPositionList (dataPair id:id position:item.verts[id].position) newObject = dataPair obj:item data:idPositionList append this.objectEdgeVertList newObject ) --test the objectEdgeVertList for coincident verts -- this.PrintObjectEdgeVertList() --test for coincident verts on single objects for item in objectEdgeVertList do ( for pair in item.data do ( for compare in item.data where pair != compare do ( if (distance pair.position compare.position) < this.tolerance then this.AppendMatchList pair.position item.obj pair.id item.obj compare.id ) ) ) --compare objects for coincident verts --get a set of objects that are close enough to each other to have coincident vertices this.ProximityCull() local numObjs = objectEdgeVertList.count if (objectEdgeVertList.count > 1) then ( for i = 1 to numObjs do ( for j = i + 1 to numObjs do ( if (this.ProximityTest objectEdgeVertList[i].obj objectEdgeVertList[j].obj) then ( for item in objectEdgeVertList[i].data do ( local vertPosition = item.position for test in objectEdgeVertList[j].data do ( if distance item.position test.position < this.tolerance then ( this.AppendMatchList item.position objectEdgeVertList[i].obj item.id objectEdgeVertList[j].obj test.id ) ) ) ) ) ) ) ) else print "Please select a valid object." --if we have coincident vertices, get the face data if (this.matchList.count > 0) then ( this.GetCOVERT_Objects() return true ) else return false ), -------------------------------------------------------------------------------------------------------------------------------- --PRINT FUNCTIONS -------------------------------------------------------------------------------------------------------------------------------- fn PrintObjectEdgeVertList = ( for item in this.objectEdgeVertList do ( format "Name: %\n" item.obj.name for this in item.data do ( format "id: %\t%\n" this.id this.position ) format "\n" ) ), fn PrintCOVERT_List = ( for match in this.matchList do ( format "Position: %\n" match.position for object in match.objectList do ( format "Object: %\t" object.obj.name format "IDs: " for id in object.vertList do ( format "% " id ) format "\n" ) format "\n" ) format "Objects: %" this.objList[1].name for object in this.objList where object != this.objList[1] do ( format ", %" object.name ) format "\n" format "Tolerance: %\n" this.tolerance ) ) -------------------------------------------------------------------------------------------------------------------------------- --OBJDATA COMMANDS -------------------------------------------------------------------------------------------------------------------------------- fn OBJDATA_GetVertNormsUsingSmoothingGroups obj vert = ( local faces = (polyop.getFacesUsingVert obj #{vert}) as array local OBJDATA_NormalList = #() local groupedList = this.GroupFacesBySmoothingGroup obj faces -- go through each list member and get the average normal for item in groupedList do ( local vertexNormal = [0,0,0] local normalOp --alias for normal operation if (classOf obj == editable_mesh) then normalOp = getFaceNormal else normalOp = polyop.getFaceNormal for id in item.faceids do ( vertexNormal += normalOp obj id ) append OBJDATA_NormalList (OBJDATA_Normal vector:(normalize vertexNormal) smoothingGroups:item.smoothingGroups vertexID:vert faceList:item.faceids) ) return OBJDATA_NormalList ) --structure used by OBJDATA_Ops.GetSmoothingGroupsUsingNormals struct OBJDATA_Normal ( vector = [0,0,0], smoothingGroups = #{}, vertexID, faceID ) -------------------------------------------------------------------------------------------------------------------------------- --TEST COMMANDS -------------------------------------------------------------------------------------------------------------------------------- -- timeValue = timestamp() -- COVERT = COVERT_List() -- COVERT.InitCOVERT_List (selection as array) -- COVERT.PrintCOVERT_List() -- format (((timestamp() - timeValue) as float / 1000) as string + " seconds\n")