[Closed] Getting the longest edgeloop of an object
Hey guys! So, I want to find the longest edgeloop of an object. I have an idea of how to go about it, but might be a bit messy, so I thought I’d ask here first.
My idea is the following:
[ul]
[li]Get all edgeloops of the object (not sure how to do this?)
[/li][li]For each edgeloop, store the edges in an array. Then convert the current loop of edges to a spline, measure the length of the spline, store it in an array
[/li][li]Find the index of the longest length from the array with the length’s in (not sure if maxscript has a good way to do that?)
[/li][li]Return the array of the edges with the index found for the longest length
[/li][/ul]
What do you think? Is this doable without too much hasle in maxscript? Or do you think it’s a better way to do this?
[ul]
[li]Find all edges loops #(#{1…5},#{6…10},#{11…30})[/li][li]For each loop, measure the distance between the vertices of each edge.[/li][/ul]
Instead of getting all the edge loops just try getting an edge, convert it to a loop, then measure it, with the method in the first comment and remove the edges from the array of all edges. With this method you can simply remove the redundancy in the iteration part of the script, because an edgeloop contains a lot of edges that has been measured before. This is good because you dont need to test every edge if it has been measured or not, because it’s not part of the whole anymore.
Very unoptimized, but I think it does the job:
(
fn GetLongestEdgesLoop node =
(
edges = node.edges as bitarray
longestLoop = #(-1E9, #{})
for j in edges do
(
polyop.setedgeselection node #{j}
node.SelectEdgeLoop()
loop = polyop.getedgeselection node
loopLength = 0
for i in loop do
(
verts = polyop.getedgeverts node i
loopLength += distance (polyop.getvert node verts[1]) (polyop.getvert node verts[2])
deleteitem edges i -- Comment this line if you want to process all edges
)
if loopLength > longestLoop[1] do
(
longestLoop[1] = loopLength
longestLoop[2] = loop
)
)
return longestLoop
)
l = GetLongestEdgesLoop $
polyop.setedgeselection $ l[2]
format "Edges : %
Length: %
" l[2] l[1]
)
i’m not sure that every edge from a loop makes exactly this loop.
so i think we have to process ALL edges
but of course the task – find the longest loop – can be set and solved for only specific cases, and cannot be in common case
Neither am I.
Perhaps it’s a good idea. We would need a few test scenarios to be sure the algorithm performs as expected.
Breaking it into points:
-
put all edges into an array —> alledgearray = #(1…100)
-
get first edge from the array
-
convert it to an edge loop
-
get the loop edges
-
mesaure it
-
test the legth if it is greater than the last measured loop
-
if it’s greater, store the edgeloop array and the length of this loop
-
remove the edge loop array from the alledgearray (you can do this by converting both array into a bitarray, than alledgearray – edgeloop)
And do this all things until all the edges has been removed from the alledgearray
That’s what I’m thinking:
function genLoopEdgeArray theObj theEdge = (
selEdge = getEdgeSelection theObj
polyop.setEdgeSelection theObj theEdge
theObj.SelectEdgeLoop()
edgeLoop = getEdgeSelection theObj
return edgeLoop
)
function genAllLoops = (
allEdgesArray = #{1..(polyop.getNumEdges $)} as array
escapeEnable = true
while allEdgesArray.count != 0 do (
theLoop = genLoopEdgeArray $ allEdgesArray[1]
allEdgesArray = ((allEdgesArray as bitarray) - (theLoop as bitarray)) as array
print theLoop
)
)
genAllLoops()
If you use this method instead of looping through all the edges, you save a huge amount of time (on high poly meshes), because with this the search is going through the loops instead of looping through all the edges one by one.
This script lists all the individual loops.
The function I published above, while unoptimized, runs about 25% faster and uses about 60 times less memory.
It return the longest loop and it’s length.
If you need to iterate over all the edges, you can just comment 1 line of code.
If you need to print all the edges loops you can just add “print loop” call after the “for i” iteration.
it is the same bad case there…
NOT EVERY EDGE IN A LOOP MAKES EXACT THIS LOOP!
I get your point, but I don’t get it. Does it sound ambiguous? Well, it might be then.
I think you are talking about improving the Max loop algorithm, or at least trying to show that the loop algorithm fails in some cases. One common case where it looks like it fails is with open edges. For example using a plane, one would expect that selecting any of the open edges and looping it would result in the whole perimeter being selected. Is that one of the cases you are trying to point out?
The function I wrote is based on what any user would understand for loop. Meaning that for most users, a loop will be what the Loop button produces.
The OP did not specify anything different from this, so I had no reason to look for further into improving the loop algorithm.
But you have a good point if you would like to improve it.
Wow!
Ok I see the point!
I think I have to modify nearly all of my scripts to make them faster. I made a mistake when I started using the simplest way for “for loops” (i=1 to something.count). It’s insanely slow compared to the “i in something” expression in most cases… The best thing in this is that my scripts aren’t slow at all, but it’s good to see, that I can make them even faster.
So thank you, I think I have learned a very good thing today. It was a HUGE help for me!
just interesting… what do you think about how max makes a poly(or mesh) loop?