[Closed] Best way to find edge under mouse?
I have a script where I determine the edge that a user is hovering the mouse over (I have included a simplified version below). Right now, I am finding the nearest vertex, and then the -next- nearest vertex, and using the line that connects the two.
This works pretty well so long as the edges in the area are all of roughly equal length. However, when dealing with faces that are long and skinny, it becomes necessary to hover the mouse exactly over the middle of the edge you want to select.
What would be a better way to approach this?
global restartTool = false
global vertCount, backVerts, okVerts, hotEdge
----------------------------------------------------------------
-- Function to determine the distance between a point and a line
-- Special thanks to prettyPixel
----------------------------------------------------------------
fn pointLineDist pA pB pC =
(
local vAB = pB - pA
local vAC = pC - pA
(length (cross vAB vAC)) / (length vAB)
)
------------------------------------------------------
-- Function to determine the edge closest to the mouse
------------------------------------------------------
fn getMouseEdge =
(
vertCount = polyop.getNumVerts $.baseobject
backVerts = (polyop.getVertsByFlag $.baseobject 8)
okVerts = (#{1..vertCount} - backVerts - (polyop.getHiddenVerts $.baseobject)) as array
if vertCount != 0 do
(
mp = mouse.pos
-- Find non-hidden, front facing vertex closest to the mouse
------------------------------------------------------------
vertDistArray = #(#(),#())
for v in okVerts do
(
m = gw.wTranspoint (polyop.getVert $.baseobject v node:$)
append vertDistArray[1] v
append vertDistArray[2] (distance mp [m.x, m.y])
)
minIndex = findItem vertDistArray[2] (aMin vertDistArray[2])
minVert = vertDistArray[1][minIndex]
------------------------------------------------------------
-- Find closest neighboring vertex
-----------------------------------------------------------------------
vertEdges = polyOp.getEdgesUsingVert $ minVert
nVerts = ((polyOp.getVertsUsingEdge $ vertEdges) - #{minVert}) as array
nDistArray = #(#(), #())
for v in nVerts do
(
m = gw.wTranspoint (polyop.getVert $.baseobject v node:$)
append nDistArray[1] v
append nDistArray[2] (distance mp [m.x, m.y])
)
nMinIndex = findItem nDistArray[2] (aMin nDistArray[2])
nMinVert = nDistArray[1][nminIndex]
-----------------------------------------------------------------------
nVertEdges = polyOp.getEdgesUsingVert $ nMinVert
hotEdge = (vertEdges - (vertEdges - nVertEdges))
) -- end if (vertCount != 0)
completeredraw()
gw.setcolor #line (yellow)
gw.polyLine #(polyOp.getVert $ minVert, polyOp.getVert $ nMinVert) false
gw.enlargeUpdateRect #whole
gw.updateScreen()
) -- end function (getMouseEdge)
--------------------------------
tool getEdgeLoop
(
on freeMove do getMouseEdge()
on mousePoint clickno do
(
getMouseEdge()
edges = polyOp.getEdgeSelection $ + hotEdge
$.selectedEdges = edges
$.selectedgeloop()
restartTool = true; #stop
)
on mouseAbort clickno do (restartTool = false) -- do not restart mouse tool on abort
on stop do if restartTool == true do startTool getEdgeLoop
)
if $ != undefined do startTool getEdgeLoop
You can use intersectRayEx to find the face under the mouse and the exact point where the mouse hit that face.
Then you could calculate the distance between that point and the 3 edges of that face to determin wich edge is the closest.
Hope this is what you were trying to do…
Hm… that seems like it might be a more efficient way of doing what I’m doing, but I question whether the results would be any different? Also, I don’t think it should make a difference, but this is really geared more toward working with quad-based polys rather than with tri-based meshes…