Угол между полигонами
- Автор темы kolts
- Дата создания
Я бы попробовал проверить по знаку координат в векторе
в первом квадранте = +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 если нет то меньше
Надеюсь в этом есть смысл
в первом квадранте = +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 если нет то меньше
Надеюсь в этом есть смысл
Вложения
-
65,7 КБ Просмотров: 378
kolts
Условия:
1. Полигоны должны иметь одно общее ребро (Edge).
2. Полигоны должны быть плоскими (planar) и выпуклыми (convex).
Выпуклый многоугольник (полигон) это многоугольник без самопересечений такой, что каждый внутренний угол которого не более 180 градусов.
Если эти условия соблюдаются для твоего случая, тогда попробуй так:
1. Запусти скрипт.
2. Выдели 2 полигона, для которых соблюдаются условия.
3. Нажми кнопку "Get angle".
Объект должен быть Editable Poly (без модификаторов).
Условия:
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)
2. Выдели 2 полигона, для которых соблюдаются условия.
3. Нажми кнопку "Get angle".
Объект должен быть Editable Poly (без модификаторов).
Работает только надо поменять "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
)