# Getting loop direction

 02 February 2013 #1 Ian31R Expert portfolio Ian Adams Freelancer Kent, USA   Join Date: Aug 2011 Posts: 294 Getting loop direction Was wondering if anyone knew how to get the previous and next edges in an edge loop. I'm able to get both edges by getting the edge's vertices, converting that to edges and subtracting that by edges converted by the original edge's faces on both sides of the edge. Here's an example - `````` Edge1 = (polyop.getEdgeSelection \$ as array)[1] Verts = polyop.getVertsUsingEdge \$ #(Edge1) Edges = polyop.getEdgesUsingVert \$ Verts Faces = polyop.getFacesUsingEdge \$ #{Edge1} SideEdges = Edges - (polyop.getEdgesUsingFace \$ Faces) `````` I figured you could get the previous and next edges in the loop by which edge index is higher, but I noticed that in various geometries, that you can't use that because the edge indices of the entire loop isn't always sequential. Should I be getting the edges by which vertex is higher or lower instead? Or should I try picking edges by an average of local face positions, maybe by using polyop.getFaceCenter? Unfortunately, I'm not that good with transformations. I also realized, I'll have to check for cases when the current edge is at the beginning or end of a loop. Also, I noticed that special cases where the current edge is at a pole presents a problem, like at the bottom or top of a sphere. The main reasons I'm trying to figure this out, instead of using setLoopShift, is so that I can then know how to make a similar function for meshes and patches. Also I try to avoid having to make selections whenever possible. Thanks in advance! share quote
 02 February 2013 #2 miauu Expert   portfolio Kostadin Kotev Blagoevgrad, Bulgaria   Join Date: Sep 2009 Posts: 856 Try this: For open edge loop: - find the "starting edge" - this is edge that have only one neighbor edge from the loop edges - then, using your code find the next edges and so on. For closed edge loop - get one edge, mark it as "starting edge" - get one vert of this edge and find the next edges. When the next edge is the "starting edge" - stop, because all edges from the loop are processed. Store the edge indexes in array, because the bitarray will rearenge them and you will loose the edge's order. __________________ share quote
 02 February 2013 #3 Ian31R Expert portfolio Ian Adams Freelancer Kent, USA   Join Date: Aug 2011 Posts: 294 Hey thanks for the quick reply. So, with this method I would have to do a whole loop to begin with to test if its open or not right? How do you manually get all the edges in the loop, by using my method to get both side edges, and keep adding that to an array until the array count stops changing? I think you can test for a closed loop, if the number of edges == the number of verts in the loop, right? With a closed loop, how would you decide the first edge, maybe just the lowest index in the loop? I know t doesn't matter, just curious what you would do. It would be great to see the source for the original setloopshift function. My goal is make that for all 3 geometry types, along with setringshift. share quote
 02 February 2013 #4 miauu Expert   portfolio Kostadin Kotev Blagoevgrad, Bulgaria   Join Date: Sep 2009 Posts: 856 Why you want to duplicate built in SetLoopShift? This code works for open edge loop. To test it select some edges that have common verts. They can form a loop or... Optimize it and addapt to works with closed edge loop. ``````( curO = selection[1] selEdges = polyop.getEdgeSelection curO edgeVerts = polyop.getVertsUsingEdge curo selEdges oneEdgeVerts = for v in edgeVerts where ( (selEdges * (polyop.getEdgesUsingVert curO v)).numberset == 1) collect v vL1 = #{oneEdgeVerts[1]} thisEdgeLoop = #() e0 = #{} for vv in edgeVerts do ( e1 = (selEdges * (polyop.getEdgesUsingVert curO vL1)) - e0 if not e1.isEmpty then ( for i in e1 do appendIfUnique thisEdgeLoop i vL1 = (polyop.getVertsUsingEdge curO e1) - vL1 e0 = e1 ) ) format "Edge order: % \n" thisEdgeLoop )`````` __________________ share quote
 02 February 2013 #5 Ian31R Expert portfolio Ian Adams Freelancer Kent, USA   Join Date: Aug 2011 Posts: 294 Well I'm trying to duplicate it so I can figure out how it works, so I can do the same for meshes and patches. I also plan on making my own loop functions that aren't in poly tools. I figured just getting the loop's edges instead of needing to select them, getting that selection, and restoring the previous edge selection, would be easier and faster. For example, if I needed to test if a loop is open, or how many edges are in the current loop, or get a random selection within that loop, these would be cases where I need the loop's edge's. I would think that in most selection scripts, you should only need to set the selection once, at the end. Your edge order method looks pretty good. I just finished a function to get the whole edge loop. So getting the edge order of that loop, should help. The function seems to work decent. Haven't tested it extensively on different geometries though. `````` fn LoopPolyEdge Obj:\$ Sel:(polyop.getEdgeSelection \$) SetSelect:false = ( if (Obj != undefined and Sel != undefined and Sel.numberset >= 1) then ( local LoopEdgeSel = #{} -- Initial selection for i in Sel where (LoopEdgeSel[i] != true) do ( local EdgeLoop = #{i} -- Initial selection for j = 1 to (polyop.getNumEdges Obj) do ( local OldSelCount = EdgeLoop.numberset -- Get previous bitarray count local PoleVerts = (for k in (polyop.getVertsUsingEdge Obj EdgeLoop) where ((polyop.getEdgesUsingVert Obj k).numberset > 4) collect k) as bitarray -- Get vertices in selection, whose edges are more than 4 local PoleEdges = polyop.getEdgesUsingVert Obj PoleVerts -- Get edges from pole vertices local Verts = polyop.getVertsUsingEdge Obj EdgeLoop -- Get verts from current edge local Edges = polyop.getEdgesUsingVert Obj Verts -- Get verts from current edge local FaceEdges = polyop.getEdgesUsingFace Obj (polyop.getFacesUsingEdge Obj EdgeLoop) -- Get vertices from faces on both sides of edge local NewEdges = (Edges - FaceEdges - PoleEdges) + EdgeLoop -- Get edges within loop local BorderEdges = polyop.getOpenEdges Obj -- Get open edges if ((BorderEdges * NewEdges).numberset != 0) then ( for k in NewEdges where (BorderEdges[k] != true) do ( local EdgeFaces = polyop.getFacesUsingEdge Obj k -- Get edge's faces local FaceEdges1 = polyop.getEdgesUsingFace Obj #{(EdgeFaces as array)[1]} -- Get edges from face 1 local FaceEdges2 = polyop.getEdgesUsingFace Obj #{(EdgeFaces as array)[2]} -- Get edges from face 2 NewEdges = (NewEdges - (FaceEdges1 + FaceEdges2)) + (FaceEdges1 * FaceEdges2) -- Get rid of edges not in loop ) -- For edges that aren't on border, get only the edge that's between the two faces ) -- If any edges in selection are open EdgeLoop = NewEdges -- Put edges to edge loop if (OldSelCount == EdgeLoop.numberset) then exit -- If selection doesn't change anymore ) -- Keep growing loop until its full LoopEdgeSel += EdgeLoop -- Add edge loop to bitarray ) -- Loop through edge selection, getting loop from edge, ignoring any edges that are already looped if (SetSelect == true) then polyop.setEdgeSelection Obj LoopEdgeSel -- Select edges return LoopEdgeSel -- Get edge loop selection ) else return Sel -- Get original selection )`````` share quote
 02 February 2013 #6 Ian31R Expert portfolio Ian Adams Freelancer Kent, USA   Join Date: Aug 2011 Posts: 294 Just updated function to try to deal with the ngons that the sphere in your picture has - `````` fn LoopPolyEdge Obj:\$ Sel:(polyop.getEdgeSelection \$) SetSelect:false = ( if (Obj != undefined and Sel != undefined and Sel.numberset >= 1) then ( local LoopEdgeSel = #{} -- Initial selection for i in Sel where (LoopEdgeSel[i] != true) do ( local EdgeLoop = #{i} -- Initial selection for j = 1 to (polyop.getNumEdges Obj) do ( local OldSelCount = EdgeLoop.numberset -- Get previous bitarray count local PoleVerts = (for k in (polyop.getVertsUsingEdge Obj EdgeLoop) where ((polyop.getEdgesUsingVert Obj #{k}).numberset > 4) collect k) as bitarray -- Get vertices in selection, whose edges are more than 4 local PoleEdges = polyop.getEdgesUsingVert Obj PoleVerts -- Get edges from pole vertices local Verts = polyop.getVertsUsingEdge Obj EdgeLoop -- Get verts from current edge local Edges = polyop.getEdgesUsingVert Obj Verts -- Get verts from current edge local FaceEdges = polyop.getEdgesUsingFace Obj (polyop.getFacesUsingEdge Obj EdgeLoop) -- Get vertices from faces on both sides of edge local NewEdges = (Edges - FaceEdges - PoleEdges) + EdgeLoop -- Get edges within loop local BorderEdges = polyop.getOpenEdges Obj -- Get open edges if not (BorderEdges * NewEdges).isEmpty then ( for k in NewEdges where (BorderEdges[k] != true) do ( local EdgeFaces = polyop.getFacesUsingEdge Obj #{k} -- Get edge's faces local FaceEdges1 = polyop.getEdgesUsingFace Obj #{(EdgeFaces as array)[1]} -- Get edges from face 1 local FaceEdges2 = polyop.getEdgesUsingFace Obj #{(EdgeFaces as array)[2]} -- Get edges from face 2 NewEdges = (NewEdges - (FaceEdges1 + FaceEdges2)) + (FaceEdges1 * FaceEdges2) -- Get rid of edges not in loop ) -- For edges that aren't on border, get only the edge that's between the two faces ) -- If any edges in selection are open EdgeLoop += NewEdges -- Put edges to edge loop if (OldSelCount == EdgeLoop.numberset) then exit -- If selection doesn't change anymore ) -- Keep growing loop until its full local VertLoop = polyop.getVertsUsingEdge Obj EdgeLoop -- Get vertices in loop local NGonVerts = #{} -- Initial vert selection for j in VertLoop where ((polyop.getEdgesUsingVert Obj #{j}).numberset == 3 and (polyop.getFacesUsingVert Obj #{j}).numberset == 3) do append NGonVerts j -- Get vertices with 3 edges and 3 faces if not NGonVerts.isEmpty then ( local Edges = #{} -- Initial edge selection for j = 1 to VertLoop.numberset do Edges += (polyop.getEdgesUsingVert \$ (VertLoop as array)[j]) * (polyop.getEdgesUsingVert \$ (VertLoop - #{(VertLoop as array)[j]})) -- Get edges joined by vertices EdgeLoop += Edges -- Add edges to edge loop ) -- If there are any vertices with 3 edges and 3 faces at all LoopEdgeSel += EdgeLoop -- Add edge loop to bitarray ) -- Loop through edge selection, getting loop from edge, ignoring any edges that are already looped if (SetSelect == true) then polyop.setEdgeSelection Obj LoopEdgeSel -- Select edges return LoopEdgeSel -- Get edge loop selection ) else return Sel -- Get original selection ) `````` share quote
 02 February 2013 #7 Ian31R Expert portfolio Ian Adams Freelancer Kent, USA   Join Date: Aug 2011 Posts: 294 Including your method for open loops, I just finished a function to get the edge order for closed and open loops. for closed loops, it subtracts the first vertex from the loop's vertices, and gets the first edge from that vertex, adds that to array first, then collects the others, then adds the last edge from the first vertex. `````` fn GetLoopOrderPolyEdge Obj:\$ Sel:(polyop.getEdgeSelection \$) Reverse:false = ( if (Obj != undefined and Sel != undefined and Sel.numberset >= 1) then ( local EdgeLoopSel = #() -- Initial selection local EdgeVerts = polyop.getVertsUsingEdge Obj Sel if (Sel.numberset == EdgeVerts.numberset) then ( local MiddeleVert = (EdgeVerts as array)[1] -- Get last vertex in vert selection local OpenVertLoop = (EdgeVerts - #{MiddeleVert}) -- Get vert selection except the first one local SideVerts = (OpenVertLoop * (polyop.getVertsUsingEdge Obj (polyop.getEdgesUsingVert Obj MiddeleVert))) as array -- Get vertices on either side of the first one local StartVert = #{SideVerts[1]} -- Get first vertice next to the first one local EndVert = SideVerts[SideVerts.count] -- Get last vertice next to the first one local Edge0 = #{} -- First edge local StartEdge = (((polyop.getEdgesUsingVert Obj MiddeleVert) * (polyop.getEdgesUsingVert Obj StartVert)) as array)[1] -- Get starting edge local EndEdge = (((polyop.getEdgesUsingVert Obj MiddeleVert) * (polyop.getEdgesUsingVert Obj EndVert)) as array)[1] -- Get ending edge local OpenEdgeLoop = (Sel - #{StartEdge, EndEdge}) -- Remove start and end edges append EdgeLoopSel StartEdge -- Add starting edge to array for i in OpenVertLoop do ( local Edge1 = (OpenEdgeLoop * (polyop.getEdgesUsingVert Obj StartVert)) - Edge0 -- Get edge if not Edge1.isEmpty then ( for j in Edge1 do appendIfUnique EdgeLoopSel j -- Add edge to array StartVert = (polyop.getVertsUsingEdge Obj Edge1) - StartVert -- Get next vertex Edge0 = Edge1 -- Remove edge )-- If there is an edge ) -- Loop through vertices append EdgeLoopSel EndEdge -- Add ending edge to array ) else -- Closed loop ( local SingleEdgeVerts = for i in edgeVerts where ((Sel * (polyop.getEdgesUsingVert Obj i)).numberset == 1) collect i -- Get vertices at both ends local Vert1 = #{SingleEdgeVerts[1]} -- Get first vertex local Edge0 = #{} -- First edge for i in EdgeVerts do ( local Edge1 = (Sel * (polyop.getEdgesUsingVert Obj Vert1)) - Edge0 -- Get edge if not Edge1.isEmpty then ( for j in Edge1 do appendIfUnique EdgeLoopSel j -- Add edge to array Vert1 = (polyop.getVertsUsingEdge Obj Edge1) - Vert1 -- Get next vertex Edge0 = Edge1 -- Remove edge )-- If there is an edge ) -- Loop through vertices ) -- Open loop if (EdgeLoopSel.count > 0 and Reverse == true) then ( InvArray = #() -- Initial selection for i = (EdgeLoopSel.count) to 1 by -1 do append InvArray EdgeLoopSel[i] -- Add elements to resulting array backwards EdgeLoopSel = InvArray -- Get reversed array ) -- If reverse is true and array is not empty return EdgeLoopSel -- Get edge loop selection ) else return Sel -- Get original selection ) `````` Now I can get the previous and next edge in the ordered array. For closed loops though, I'll have to check when I'm trying to get the next edge, and the current edge is the last one, then make the next one be the first, and the previous edge will be checked with the first edge. Thanks for the help miauu. share quote
 02 February 2013 #8 CGTalk Moderation Expert   Join Date: Sep 2003 Posts: 1,066,473 Thread automatically closed This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum. __________________ CGTalk Policy/Legalities Note that as CGTalk Members, you agree to the terms and conditions of using this website. share quote

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts vB code is On Smilies are On [IMG] code is On HTML code is Off CGSociety Society of Digital Artists www.cgsociety.org Powered by vBulletinCopyright ©2000 - 2006, Jelsoft Enterprises Ltd.