среда, 3 июня 2015 г.

Скрипт по поиску пересечения объектов.

Писался на коленке, имеет очень большой потенциал для оптимизации и, соответственно, ускорения.


----------------------------------------------------------------------------------------------max2014
rollout ObjInt "Objects Intersection" width:400
(
   
    button create01 "Create" width:100 align:#center
    group "Parameters Objects"
    (
        label lblt1 "---------  Object 1  -------------------" align:#center
        spinner obj1x "X:" width:100    range:[-1000.0,1000.0, 8.0] type:#float align:#right across:4
        spinner obj1y "Y:" width:100  range:[-1000.0,1000.0, 0.0] type:#float align:#right
        spinner obj1z "Z:" width:100 range:[-1000.0,1000.0,4.0] type:#float   align:#right
        spinner obj1rad "Rad:" width:100 range:[-1000.0,1000.0,20.0] type:#float   align:#right
        label lblt2 "-----------  Object 2  ------------------" align:#center
        spinner obj2x "X:" width:100    range:[-1000.0,1000.0, 30.0] type:#float align:#right across:4
        spinner obj2y "Y:" width:100  range:[-1000.0,1000.0, 0.0] type:#float align:#right
        spinner obj2z "Z:" width:100 range:[-1000.0,1000.0,0.0] type:#float   align:#right
        spinner obj2rad "Rad:" width:100 range:[-1000.0,1000.0,10.0] type:#float   align:#right
    )       
--**********************
fn CreateSP PointA PointB theCol =
(
    local SP = SplineShape name: (uniquename "spline")
    addNewSpline SP
   
    addKnot SP 1 #corner #line PointA
    addKnot SP 1 #corner #line PointB
    SP.wirecolor = theCol   
    SP.render_displayRenderMesh = true
    SP.render_viewport_thickness = 0.2
    updateShape SP
    )
--**********************
fn createObjects =
(
    try(delete objects)catch()
    local obj1 = GeoSphere pos: [obj1x.value, obj1y.value, obj1z.value] radius: obj1rad.value name:(uniquename "sphere") segs:2,
            obj2 = GeoSphere pos: [obj2x.value, obj2y.value, obj2z.value] radius: obj2rad.value name:(uniquename "sphere") segs:2
    )
--************************   
fn PointInFace P1 P2 P3 P =
(
    local vec1 = P2 - P1
    local vec2 = P3 - P1
    local squareFace = (length(cross vec1 vec2))/2.0
-----
    local vec3 = P1 - P
    local vec4 = P2 - P
    local squareFace1 = (length(cross vec3 vec4))/2.0
-----
    local vec5 = P2 - P
    local vec6 = P3 - P
    local squareFace2 = (length(cross vec5 vec6))/2.0
----
    local vec7 = P3 - P
    local vec8 = P1 - P
    local squareFace3 = (length(cross vec7 vec8))/2.0
   
local sumArea = squareFace1 + squareFace2 + squareFace3
if sumArea <= 1.000001*squareFace then return(true) else return(false)
   
    )   
--************************   
fn findInterLinePlane planeP1 planeP2 planeP3 lineP1 lineP2 =
(
    local n = cross (planeP2-planeP1) (planeP3-planeP1)
    local normalPlane = n/(length n)

local V = planeP1 - lineP1,
        D = dot normalPlane V,
        W = lineP2 - lineP1,
        theE = dot normalPlane W
local thePos = if theE != 0 then lineP1 + W*D/theE else (lineP1 + lineP2)/2.0
   
local LengthPos = length (lineP1 - thePos) + length (lineP2 - thePos)
local lengthLine = 1.000001*length(lineP1 - lineP2)

if (LengthPos <= lengthLine) and (PointInFace planeP1 planeP2 planeP3 thePos == true) then return(thePos) else return(undefined)
    )
--************************   
--************************   
fn findInterFaces planeP1 planeP2 planeP3 lineP1 lineP2 =
(
   
    local n = cross (planeP2-planeP1) (planeP3-planeP1)
    local normalPlane = n/(length n)

local V = planeP1 - lineP1,
        D = dot normalPlane V,
        W = lineP2 - lineP1,
        theE = dot normalPlane W
local thePos = if theE != 0 then
(
    lineP1 + W*D/theE
    )     else (lineP1 + lineP2)/2.0
   
local LengthPos = length (lineP1 - thePos) + length (lineP2 - thePos)
local lengthLine = 1.000001*length(lineP1 - lineP2)

if (LengthPos <= lengthLine) and (PointInFace planeP1 planeP2 planeP3 thePos == true) then return(thePos) else return(undefined)
    )
--************************   
fn findTriagInter faceA faceB =
(
local A = faceA[1],
        B = faceA[2],
        C = faceA[3],
        M1 = faceB[1],
        M2 = faceB[2],
        M3 = faceB[3]
local theArr = #()
if findInterLinePlane A B C M1 M2 != undefined do append theArr (findInterLinePlane A B C M1 M2)
if findInterLinePlane A B C M1 M3 != undefined do append theArr (findInterLinePlane A B C M1 M3)
if findInterLinePlane A B C M2 M3 != undefined do append theArr (findInterLinePlane A B C M2 M3)
----
if findInterLinePlane M1 M2 M3 A B != undefined do append theArr (findInterLinePlane M1 M2 M3 A B)
if findInterLinePlane M1 M2 M3 A C != undefined do append theArr (findInterLinePlane M1 M2 M3 A C)
if findInterLinePlane M1 M2 M3 B C != undefined do append theArr (findInterLinePlane M1 M2 M3 B C)

if theArr.count == 2 do CreateSP theArr[1] theArr[2] red
    )
--************************
fn getObjInter object1 object2 =
(
progressstart "Iteration ..."

    convertToMesh object1
    convertToMesh object2
    local n = 0
    local numf = object1.numfaces
    for i in object1.faces do
    (
        local face1 = #()
        local index1 = (meshop.getVertsUsingFace object1 i.index) as array
        append face1 (getVert object1 index1[1])
        append face1 (getVert object1 index1[2])
        append face1 (getVert object1 index1[3])
        for j in object2.faces do
        (
            local face2 = #()
            local index2 = (meshop.getVertsUsingFace object2 j.index) as array
            append face2 (getVert object2 index2[1])
            append face2 (getVert object2 index2[2])
            append face2 (getVert object2 index2[3])
            findTriagInter face1 face2

            )
progressupdate (100.0*n/numf)
n+=1
        )
progressend ()   
    )   
--************************   
fn theAllFunc =
(
    createObjects()
    getObjInter $sphere001 $sphere002
    )
   
--************************
   
on create01 pressed do theAllFunc()   
--------------------------------   
on obj1x changed val do theAllFunc()
on obj1y changed val do theAllFunc()
on obj1z changed val do theAllFunc()
on obj1rad changed val do theAllFunc()
on obj2x changed val do theAllFunc()
on obj2y changed val do theAllFunc()
on obj2z changed val do theAllFunc()
on obj2rad changed val do theAllFunc()
)--end rollout
createDialog ObjInt  escapeEnable: true

--------------------------------------------------------------------------------------

Test face intesection.




----------------------------------------------------------------------------------
rollout testFaceInt "test Face Intersection" width:400
(
    button create01 "Create" width:100 align:#center
    group "Parameters T1"
    (
        label lblt0 "M1 [x1, y1, z1], M2 [x2, y2, z2], M3 [x3, y3, z3]" align:#center
        label lblt1 "-------------------------------------" align:#center
        spinner x1 "x1  " width:100    range:[-1000.0,1000.0,-5.9] type:#float align:#right across:3
        spinner y1 "y1" width:100  range:[-1000.0,1000.0,-8.5] type:#float align:#right
        spinner z1 "z1 " width:100 range:[-1000.0,1000.0,12.5] type:#float   align:#right
        label lblt2 "-------------------------------------" align:#center
        spinner x2 "x2  " width:100    range:[-1000.0,1000.0,-9.4] type:#float align:#right across:3
        spinner y2 "y2" width:100  range:[-1000.0,1000.0,-12.7] type:#float align:#right
        spinner z2 "z2 " width:100 range:[-1000.0,1000.0,3.8] type:#float   align:#right
        label lblt3 "-------------------------------------" align:#center
        spinner x3 "x3  " width:100    range:[-1000.0,1000.0,-4.3] type:#float align:#right across:3
        spinner y3 "y3" width:100  range:[-1000.0,1000.0,-11.2] type:#float align:#right
        spinner z3 "z3 " width:100 range:[-1000.0,1000.0,10.2] type:#float   align:#right
    )       
    group "Parameters T2"
    (
        label lblt4 "A [a1, b1, c1], B [a2, b2, c2], C [a3, b3, c3]" align:#center
        label lblt5 "-------------------------------------" align:#center
        spinner a1 "a1  " width:100    range:[-1000.0,1000.0,-10.3] type:#float align:#right across:3
        spinner b1 "b1" width:100  range:[-1000.0,1000.0,-3.8] type:#float align:#right
        spinner c1 "c1 " width:100 range:[-1000.0,1000.0,14.0] type:#float   align:#right
        label lblt6 "-------------------------------------" align:#center
        spinner a2 "a2  " width:100    range:[-1000.0,1000.0,-8.8] type:#float align:#right across:3
        spinner b2 "b2" width:100  range:[-1000.0,1000.0,-9.8] type:#float align:#right
        spinner c2 "c2 " width:100 range:[-1000.0,1000.0,7.7] type:#float   align:#right
        label lblt7 "-------------------------------------" align:#center
        spinner a3 "a3  " width:100    range:[-1000.0,1000.0,-2.2] type:#float align:#right across:3
        spinner b3 "b3" width:100  range:[-1000.0,1000.0,-5.5] type:#float align:#right
        spinner c3 "c3 " width:100 range:[-1000.0,1000.0,3.3] type:#float   align:#right
    )   
--**********************
fn createM =
(
    try(delete objects)catch()
    local vert_array = #(), face_array = #(),
            v1 = [x1.value, y1.value, z1.value],
            v2 = [x2.value, y2.value, z2.value],
            v3 = [x3.value, y3.value, z3.value]
    local v11 = [a1.value, b1.value, c1.value],
            v22 = [a2.value, b2.value, c2.value],
            v33 = [a3.value, b3.value, c3.value]   
    vert_array = #(v1,v2,v3,v11,v22,v33)
    face_array = #([1,2,3], [4,5,6])

    local m = mesh vertices:vert_array faces:face_array
    m.name = uniquename "triag"
    )
--*********************
fn createOneVector startV endV theCol =
(
    local theThicness = 0.1
    local theV = endV - startV
    local theDir = normalize theV
    local theH = length theV
    local cyl = cylinder pos:startV dir: theDir height: (0.9*theH) radius:(theThicness/5.0) name: (uniquename "Vector")
    local con = cone pos:(startV + 0.9*theV) dir: theDir height: (0.1*theH) radius1:(theThicness/2.0) name: (uniquename "VectorArrow")
    cyl.wirecolor = theCol
    con.wirecolor = theCol
    )
--*********************   
fn createOneText thePos theText theCol =
(
    local textSize = 0.6
    local theVS = getViewSize()
    local theRay = mapScreenToWorldRay (theVS/2.0)
    local t = text text:theText size:textSize pos: thePos dir: -theRay.dir
    t.wirecolor = theCol
    )
fn createText =
(
    createOneText [x1.value, y1.value, z1.value] "M1" red
    createOneText [x2.value, y2.value, z2.value] "M2" red
    createOneText [x3.value, y3.value, z3.value] "M3" red
   
    createOneText [a1.value, b1.value, c1.value] "A" red
    createOneText [a2.value, b2.value, c2.value] "B" red
    createOneText [a3.value, b3.value, c3.value] "C" red
    )
--************************   
fn PointInFace P1 P2 P3 P =
(
    local vec1 = P2 - P1
    local vec2 = P3 - P1
    local squareFace = (length(cross vec1 vec2))/2.0
-----
    local vec3 = P1 - P
    local vec4 = P2 - P
    local squareFace1 = (length(cross vec3 vec4))/2.0
-----
    local vec5 = P2 - P
    local vec6 = P3 - P
    local squareFace2 = (length(cross vec5 vec6))/2.0
----
    local vec7 = P3 - P
    local vec8 = P1 - P
    local squareFace3 = (length(cross vec7 vec8))/2.0
   
local sumArea = squareFace1 + squareFace2 + squareFace3
if sumArea <= 1.000001*squareFace then return(true) else return(false)
   
    )   
--************************   
fn createVectors =
(
local A = [a1.value, b1.value, c1.value],
        B = [a2.value, b2.value, c2.value],
        C = [a3.value, b3.value, c3.value],
        M1 = [x1.value, y1.value, z1.value],
        M2 = [x2.value, y2.value, z2.value],
        M3 = [x3.value, y3.value, z3.value]
   
local N1 = cross (B-A) (C-A),
        N2 = N1/(length N1),
        cent1 = (A+B+C)/3.0
local N3 = cross (M2-M1) (M3-M1),
        N4 = N3/(length N3),
        cent2 = (M1+M2+M3)/3.0
   
createOneVector cent1 (cent1 + N2) blue
createOneVector cent2 (cent2 + N4) blue
createOneVector [0,0,0] A green
createOneVector [0,0,0] B green
createOneVector [0,0,0] C green
createOneVector [0,0,0] M1 green
createOneVector [0,0,0] M2 green
createOneVector [0,0,0] M3 green
    )
--************************   
fn findInterLinePlane planeP1 planeP2 planeP3 lineP1 lineP2 =
(
    local n = cross (planeP2-planeP1) (planeP3-planeP1)
    local normalPlane = n/(length n)

local V = planeP1 - lineP1,
        D = dot normalPlane V,
        W = lineP2 - lineP1,
        theE = dot normalPlane W
local thePos = if theE != 0 then lineP1 + W*D/theE else (lineP1 + lineP2)/2.0
   
local LengthPos = length (lineP1 - thePos) + length (lineP2 - thePos)
local lengthLine = 1.000001*length(lineP1 - lineP2)

if (LengthPos <= lengthLine) and (PointInFace planeP1 planeP2 planeP3 thePos == true) then return(thePos) else return(undefined)
    )
--************************   
fn findTriagInter =
(
local A = [a1.value, b1.value, c1.value],
        B = [a2.value, b2.value, c2.value],
        C = [a3.value, b3.value, c3.value],
        M1 = [x1.value, y1.value, z1.value],
        M2 = [x2.value, y2.value, z2.value],
        M3 = [x3.value, y3.value, z3.value]
if findInterLinePlane A B C M1 M2 != undefined do point pos: (findInterLinePlane A B C M1 M2) size:1
if findInterLinePlane A B C M1 M3 != undefined do point pos: (findInterLinePlane A B C M1 M3) size:1
if findInterLinePlane A B C M2 M3 != undefined do point pos: (findInterLinePlane A B C M2 M3) size:1
----
if findInterLinePlane M1 M2 M3 A B != undefined do point pos: (findInterLinePlane M1 M2 M3 A B) size:1
if findInterLinePlane M1 M2 M3 A C != undefined do point pos: (findInterLinePlane M1 M2 M3 A C) size:1
if findInterLinePlane M1 M2 M3 B C != undefined do point pos: (findInterLinePlane M1 M2 M3 B C) size:1

local thePoints = $Point* as array
if thePoints.count == 2 do createOneVector thePoints[1].pos thePoints[2].pos red
    )
--************************   
fn theAllFunc =
(
    createM()
    createText()
    createVectors()
    findTriagInter()
    )
   
--************************
   
on create01 pressed do theAllFunc()   
--------------------------------   
on x1 changed val do theAllFunc()
on y1 changed val do theAllFunc()
on z1 changed val do theAllFunc()
on x2 changed val do theAllFunc()
on y2 changed val do theAllFunc()
on z2 changed val do theAllFunc()
on x3 changed val do theAllFunc()
on y3 changed val do theAllFunc()
on z3 changed val do theAllFunc()
---------------------------------
on a1 changed val do theAllFunc()
on b1 changed val do theAllFunc()
on c1 changed val do theAllFunc()
on a2 changed val do theAllFunc()
on b2 changed val do theAllFunc()
on c2 changed val do theAllFunc()
on a3 changed val do theAllFunc()   
on b3 changed val do theAllFunc()
on c3 changed val do theAllFunc()
)--end rollout
createDialog testFaceInt 

----------------------------------------------------------------------------------