Render.ru

Угол между полигонами

kolts

Активный участник
Рейтинг
16
#1
Кто знает как найти угол между полигонами если между ними больше 180 градусов. Если меньше проблем нет, находим угол между нормалями Acos(dot n1 n2). Потом от 180 отнимаем полученое. Но если между полигонами больше 180 градусов не знаю как найти
 

kolts

Активный участник
Рейтинг
16
#3
Суть в том что полигонов много и мне надо находить углы между ними. Между какими то угол меньше 180 между какими то больше. Если бы была одна пара то конечно я бы так и сделал.
 

JBond

Знаток
Рейтинг
33
#4
Можно определить в каком квадранте лежит второй вектор относительно первого.
Если он лежит в области где угол будет тупым поменять его знак, вычилить арккс дот продакт и прибавить 180гр
 

kolts

Активный участник
Рейтинг
16
#5
Можно определить в каком квадранте
Но как это сделать? Не представляю как. Дело в том что если между полигонами 270 между нормалями 90, если между полигонами 90 то между нормалями тоже 90. Короче говоря надо как то понять что угол больше 180 а найти угол уже дело техники.
 

JBond

Знаток
Рейтинг
33
#6
Я бы попробовал проверить по знаку координат в векторе
в первом квадранте = +X +Y
во втором = -X + Y
в третьем = -X - Y
в четвертом = +X - Y
*************************************************************
у нас есть два вектора A и B

создаем функцию
fn ZoneCheck varVector =

( If (varVector.x > 0 )&&(varVector.y > 0 ) then b = 1
----------------------------- b = 2
----------------------------- b = 3
----------------------------- b = 4
return b
)
проверяем в каком квадранте и A и B .
Потом проверяем соотношение зоны вектора B к зоне вектора A.

if VectorZoneCheck(A) ==1 then if VectorZoneCheck(B) == 2 do Acos(dot normolizeA normolizeB) elseif VectorZoneCheck(B) == 4 do ( Acos(dot normolizeA -normolizeB) + 180)

Тут получается что если фукнция вернула для ZC(A)=1 иZC(B) =2 угол гарантировано до 180гр, если A=1 и B=4 то угол больше 180 в любом случае.
Остается вариант ZC(A)=1 и ZC(B) =3 тут все зависит от положения векторов в каких то случаях он может быть больше 180 в каких то нет.


Для этого варианта можно проверить так - нормализовать оба вектора и вектору A поменять знак .Тогда он станет лежать тоже в квадранте 3 .
Затем проверяем его координату Y если она больше координаты вектора B значит угол между ними больше 180 если нет то меньше

Надеюсь в этом есть смысл:)
 

Вложения

igorznag

Мастер
Рейтинг
103
#7
kolts
Условия:
1. Полигоны должны иметь одно общее ребро (Edge).
2. Полигоны должны быть плоскими (planar) и выпуклыми (convex).
Выпуклый многоугольник (полигон) это многоугольник без самопересечений такой, что каждый внутренний угол которого не более 180 градусов.
Если эти условия соблюдаются для твоего случая, тогда попробуй так:
Код:
rollout igorznag_get_angle "Get angle" width:160 height:60
(
edittext text_angle "" pos:[5,5] width:145
button btn_apply "Get angle" pos:[50,30]

fn get_angle obj face_index1 face_index2=
(
if(classof obj == Editable_Poly)then
(
fes1=(polyOp.getFaceEdges obj face_index1) as bitarray;
fes2=(polyOp.getFaceEdges obj face_index2) as bitarray;
fes=fes1*fes2;
if(fes.numberSet==1)then
(
fes=fes as array; fe=fes[1];
evs=polyOp.getEdgeVerts obj fe; ev=polyOp.getVert obj evs[1]
fc=polyop.getFaceCenter obj face_index1; v=fc-ev
n1=polyop.GetFaceNormal obj  face_index1; n2=polyop.getFaceNormal obj face_index2;
d=dot v n2; a=acos(dot n1 n2);
if(d>0)then a=180+a  else a=180-a
return a;
)))--fn get_angle

on btn_apply pressed do
(
text_angle.text="";
if(classof $ == Editable_Poly)then
(
faces=(polyop.getFaceSelection $) as array
if(faces.count==2)then
(
text_angle.text=(get_angle $ faces[1] faces[2]) as string
))))
createdialog igorznag_get_angle style:#(#style_titlebar, #style_border, #style_sysmenu,#style_minimizebox)
1. Запусти скрипт.
2. Выдели 2 полигона, для которых соблюдаются условия.
3. Нажми кнопку "Get angle".
Объект должен быть Editable Poly (без модификаторов).
 

kolts

Активный участник
Рейтинг
16
#8
Работает только надо поменять "if(d>0)then a=180+a else a=180-a" на "if(d>0)then a=180-a else a=180+a" Большое спасибо. В принципе мне это нужно для правильных сеток, поэтому условия будут соблюдены.
Вообще мне интересно сделать нормальный чамфер в максе. Пока накатал вот такой

Код:
macroScript QuadChamf
    category:"Kolts"
    toolTip:"Quadchamfer"
(
    rollout QuadChamferRol "QuadChamfer" width:129 height:110
    (
        fn SelectInvert obj subobj = 
        (
            local cursel = #{}--current selected subobjects
            if( subobj == 1) --subobject level verts
            do
            (
            cursel = polyop.getvertselection obj
            polyop.setvertselection obj #{1..(polyop.getnumverts obj)}
            polyop.setvertselection obj ((polyop.getvertselection obj) - cursel)
            cursel = polyop.getvertselection obj
            return cursel
            )
            if( subobj == 2) --subobject level edges
            do
            (
                cursel = polyop.getEdgeSelection obj
                polyop.setEdgeSelection obj #{1..(polyop.getNumEdges obj)}
                polyop.setEdgeSelection obj ((polyop.getEdgeSelection obj) - cursel)
                cursel = polyop.getEdgeSelection obj
                return cursel
            )
            if( subobj == 4) --subobject level edges
            do
            (
                cursel = polyop.getFaceSelection obj
                polyop.setFaceSelection obj #{1..(polyop.getNumFaces obj)}
                polyop.setFaceSelection obj ((polyop.getFaceSelection obj) - cursel)
                cursel = polyop.getFaceSelection obj
                return cursel
            )
        )

        fn quadChamferfunc obj ChamferAmount ChamferSegments =
    (
        local NumFaces = polyop.getnumfaces obj
        local A = polyop.GetEdgeSelection obj
        undo "Quad chamfer" on
        (
            obj.edgeChamferSegments = 1
            polyop.chamferEdges obj A ChamferAmount
            polyop.Setfaceselection obj #{(NumFaces+1)..(polyop.getnumfaces obj)}
            obj.EditablePoly.tessellate #Face
            local A = polyop.getedgeselection obj
            setfaceselection obj #{1..NumFaces}
            polyop.setEdgeSelection obj (polyop.getEdgesUsingFace obj (polyop.getFaceSelection obj))
            local B = polyop.getEdgeSelection obj
            polyop.setEdgeSelection obj (A - B)
            C = polyop.getVertsUsingEdge obj (polyop.getEdgeSelection obj)
            obj.Remove ()
            local D = polyop.getnumedges obj
            polyop.setvertSelection obj C        
            obj.Remove selLevel: #Vertex
             SelectInvert obj 4  --invert selected faces
            obj.EditablePoly.ConvertSelection #Face #Edge
            SelectInvert obj 2    --invert selected edges
            obj.EditablePoly.SelectEdgeLoop ()
            SelectInvert obj 4    --invert selected faces
            obj.EditablePoly.ConvertSelection #Face #Edge
            obj.EditablePoly.SelectEdgeLoop ()
            SelectInvert obj 2
            PolyToolsModeling.SetFlow false
            obj.EditablePoly.ConvertSelection #Edge #Vertex
            obj.EditablePoly.ShrinkSelection selLevel: #Vertex
            PolyToolsModeling.SetFlowVertex()
            PolyToolsModeling.SetFlowVertex()
            if(ChamferSegments == 3) do (
            polyop.chamferEdges obj (polyop.getEdgeSelection obj) (ChamferAmount/3)
            PolyToolsModeling.SetFlow false
            PolyToolsModeling.SetFlowVertex()
            )
            redrawViews()
        )    
    )
            spinner ChamferAmountspn "Amount" pos:[14,17] width:79 height:16 range:[0,1000,0]
            button ChamferBtn "Chamfer" pos:[24,72] width:67 height:22
            spinner Segmentsspn "Segs" pos:[25,42] width:67 height:16 range:[2,3,2] type:#integer
            local flag = 0
            on ChamferBtn pressed do
            (
                flag = 0
                if (classof $ == Editable_Poly and subobjectlevel == 2)  do flag = 2
                local EdgeSel = polyop.getedgeselection $                
                if EdgeSel.numberset == 0 do flag = 1
                if flag == 2 do
                quadChamferfunc $ ChamferAmountspn.value Segmentsspn.value
            )
        )

    createdialog QuadChamferRol
)
Пока несерьезно, думаю переделать и жду помощи. Какие есть идеи насчет этого
 
Сверху