Files
2025-09-29 00:52:08 +02:00

351 lines
9.9 KiB
Plaintext
Executable File

--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 <obj> <vertex>
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")