Rotating planes so that one rotationaxis is set to zero

Hello everybody,

I'm fairly new to maxscript but I have some experience with c and java.

My Problem:

Within my scenes there are planes that are placed and rotated by hand. The person who placed them now needs two values from those planes: heading and the pitch

To be more precise: The Values for pitch (or drop as it's an tectonically problem) need to be between 0-90 degrees
The Values for heading need to be between 0-360 degrees. (both eulerangles)

I don't actually need to rotate those planes in the end but I really need those values.

My solution so far:
I don't know if there is an easier way to do this in maxscript. So please point out any stupid stuff I'm doing.

1. collect all planes in the scene and convert them to poly with only one face

2. get normal vector for each plane (normalvector = polyOp.getFaceNormal 1)

3. get the "horizontal" vector for that plane (horizontalVector = normalize (cross [0,0,1] normalvector))

4. get the "vertical" vector (verticalVector = normalize (cross horizontalVector normalvector ))

5. get the vector facing to the front (frontVector = normalize ([normalvector [1], normalvector [2], 0]))

6. after all that I calculate the angle between the vertical vector and the front vector with (theAngle = acos(dot (normalize frontVector ) (normalize verticalVector )))

All the results till now were really strange. In some cases I looked like it worked correctly and in others it really wasn't right at all.

Am I missing something here? Am I using the right approach to this problem?

I can't provide any working code right now because of some strange bug in maxscript. Nevertheless would I be very thankful if anyone has an idea how this could be solved?

If you need any more code I will happily post any "non-working" snippets ;-)

Cheers,
Per

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Garp's picture

Heading of the drop?

That's exactly what my snippet finds. Did you try it?
Make a plane, rotate it randomly and run the code. Then check the result.
Note that the angle follows the usual convention, i.e. 0° points towards positive X and positive angles are CCW.

fexed's picture

I tried your code but my

I tried your code but my results weren't right.

Nevertheless I found a solution my self. Thank you anyway.

Here is my final code:

	out_name = ((GetDir #export)+"/tectdata.txt")
	out_file = createfile out_name
 
	north = [0,1,0]
 
	for obje in Shapes  where classOf obje == Section do
	(
	sectionrotation  = quatToEuler2(obje.transform.rotation)	
	p = Plane pos: [obje.pos.x, obje.pos.y, obje.pos.z] width:10 length:10 widthsegments:1 lengthsegments:1 isSelected:off
	gSHsetObjectRotation p sectionrotation.x sectionrotation.y sectionrotation.z
	obj_poly = convertToPoly(p)
 
	local nv = polyOp.getFaceNormal obj_poly 1
	if (nv.z < 0) then
		(
			addModifier p (normalModifier flip:true)
			local nv = polyOp.getFaceNormal obj_poly 1
			local fv = [nv.x, nv.y, 0]
			local hv = normalize (cross [0,0,1] nv)
			local vv = normalize (cross hv nv)
			--local heading = acos (dot nv y_axis)
			local heading = acos((nv.x * north.x +nv.y*north.y) / (sqrt(nv.x^2 + nv.y^2) * sqrt(north.x^2+north.y^2)))
 
			local drop = acos (dot nv z_axis)
			if (drop > 90) then
			( drop = 180-drop)
			format "%; %; %\n" obje.name drop heading nv fv to:out_file
		) else
		(
			local fv = [nv.x, nv.y, 0]
			local hv = normalize (cross [0,0,1] nv)
			local vv = normalize (cross hv nv)
			--local heading = acos (dot nv y_axis)
			local heading = acos((nv.x * north.x +nv.y*north.y) / (sqrt(nv.x^2 + nv.y^2) * sqrt(north.x^2+north.y^2)))
 
			local drop = acos (dot nv z_axis)
			if (drop > 90) then
			( drop = 180-drop)
			format "%; %; %\n" obje.name drop heading nv fv to:out_file
		)
 
	delete p
	)
	close out_file
 
fn gSHsetObjectRotation obj rx ry rz =
(
    -- Reset the object's transformation matrix so that 
    -- it only includes position and scale information. 
    -- Doing this clears out any previous object rotation.
    local translateMat = transMatrix obj.transform.pos
    local scaleMat = scaleMatrix obj.transform.scale
    obj.transform = scaleMat * translateMat
 
    -- Perform each axis rotation individually
    rotate obj (angleaxis rx [1,0,0])
    rotate obj (angleaxis ry [0,1,0])
    rotate obj (angleaxis rz [0,0,1])
)
fexed's picture

and one more thing...

I'm not looking for the actual object heading (the sections(planes) are randomly placed by hand). I just need the heading of the drop. hopefully that helps a little understanding the problem.

fexed's picture

Hi,

this is what i've got so far:

	out_name = ((GetDir #export)+"/tectdata.txt")
	out_file = createfile out_name
 
	north = [0,1,0]
 
	for obje in Shapes  where classOf obje == Section do
	(
	sectionrotation  = quatToEuler2(obje.transform.rotation)	
	p = Plane pos: [obje.pos.x, obje.pos.y, obje.pos.z] width:10 length:10 widthsegments:1 lengthsegments:1 isSelected:off
	gSHsetObjectRotation p sectionrotation.x sectionrotation.y sectionrotation.z
	obj_poly = convertToPoly(p)
 
	local nv = polyOp.getFaceNormal obj_poly 1
	if (nv.z < 0) then
		(
			addModifier p (normalModifier flip:true)
			local nv = polyOp.getFaceNormal obj_poly 1
			local fv = [nv.x, nv.y, 0]
			local hv = normalize (cross [0,0,1] nv)
			local vv = normalize (cross hv nv)
			local heading = acos (dot nv y_axis)
--local heading = atan2 nv.y nv.x
 
			local drop = acos (dot nv z_axis)
			if (drop > 90) then
			( drop = 180-drop)
			format "name:%, drop:%, heading:%, nv:% fv:%\n" obje.name drop heading nv fv to:out_file
		) else
		(
			local fv = [nv.x, nv.y, 0]
			local hv = normalize (cross [0,0,1] nv)
			local vv = normalize (cross hv nv)
			local heading = acos (dot nv y_axis)
--local heading = atan2 nv.y nv.x
 
			local drop = acos (dot nv z_axis)
			if (drop > 90) then
			( drop = 180-drop)
			format "name:%, drop:%, heading:%, nv:% fv:%\n" obje.name drop heading nv fv to:out_file
		)
 
)
close out_file
 
fn gSHsetObjectRotation obj rx ry rz =
(
    -- Reset the object's transformation matrix so that 
    -- it only includes position and scale information. 
    -- Doing this clears out any previous object rotation.
    local translateMat = transMatrix obj.transform.pos
    local scaleMat = scaleMatrix obj.transform.scale
    obj.transform = scaleMat * translateMat
 
    -- Perform each axis rotation individually
    rotate obj (angleaxis rx [1,0,0])
    rotate obj (angleaxis ry [0,1,0])
    rotate obj (angleaxis rz [0,0,1])
)

and I'm using the following script to generate my test enviroment:

for xr = 0 to 360 by 30 do
	(
		for yr = 0 to 360 by 30 do
		(
 
				p = section pos: [xr,yr,0] 
				gSHsetObjectRotation p xr yr 0
 
		)
	)
 
fn gSHsetObjectRotation obj rx ry rz =
(
    -- Reset the object's transformation matrix so that 
    -- it only includes position and scale information. 
    -- Doing this clears out any previous object rotation.
    local translateMat = transMatrix obj.transform.pos
    local scaleMat = scaleMatrix obj.transform.scale
    obj.transform = scaleMat * translateMat
 
    -- Perform each axis rotation individually
    rotate obj (angleaxis rx [1,0,0])
    rotate obj (angleaxis ry [0,1,0])
    rotate obj (angleaxis rz [0,0,1])
)

As you can see I implemented your samples and now all my drop angles are correct. Thank you very much for that! But ;-) ...my heading is still messed up. It seems if it is giving me less than half the time correct results and the rest is just screwed up.

What am I missing here guys?

Both the atan2 and the acos(dot v1 v2) solutions aren't working correctly.

Thanks in advance for all your help.

shanghalf's picture

hi

hi fexed , the garp 's solution is right and
work with face normal as well ( just have to convert negative angle in positive value )

i just want to give you a small advice
when you work with maxscript, dont hesitate to create small interface to check
your resutt in real time

quick new script a couple of output field
a timer then you could see really well what s happen in your test case
cut and paste when everithing s fine

obviously your calculation was bad :)

sorry

example :

north = [0,1,0]
rollout unnamedRollout "Untitled" width:388 height:265
(
Timer tmr1 "Timer" pos:[328,220] width:24 height:24 interval:100
edittext drop "" pos:[72,30] width:125 height:22
edittext dir "" pos:[72,75] width:125 height:22

on tmr1 tick do
(
if $ == undefined do return false
nv = polyOp.getFaceNormal $ 1
heading = (atan2 nv.y nv.x )
dropt = acos ( dot nv z_axis )
drop.text = ( dropt as string )
dir.text= ( heading as string )
)
)

createdialog unnamedRollout

shanghalf

Garp's picture

If I understand correctly...

theFile = createFile "C:\\testdata.txt"
for obj in geometry do
(
  local nv = obj.dir
  local drop = acos (dot nv z_axis)
  local heading = atan2 nv.y nv.x
  format "name: %, drop: %, heading: %\n" obj.name drop heading to:theFile
)
close theFile

You don't need to convert to anything.
These angles correspond to the pivot, not the geometry. If the pivot has been rotated independently of the object, you need a face normal.

fexed's picture

Hi again, two things that

Hi again,

two things that I've come up with so far.

First I simplified my code a lot:

	out_name = ((GetDir #export)+"/testdata.txt")
	out_file = createfile out_name
 
	north = [0,1,0]
	--only editable Poly in the Scene
	for obj in Geometry do
	(
	--NormalVector
		break()
	nv = polyOp.getFaceNormal obj 1
	--HorizontalVector
		break()
	hv = normalize (cross north nv)
	--VerticalVector
		break()
	vv = normalize (cross hv nv)
	--FrontVector
		break()
	fv = normalize ([nv[1], nv[2], 0])
	drop = acos(dot vv fv)
		break()
	heading = acos(dot fv [0,1,0])
		break()
	format "name:%, drop:%, heading:%, nv:%\n" obj.name drop heading nv to:out_file
		break()
	)
	close out_file

And second I created a testing setup here:

for xr = 0 to 360 by 45 do
	(
		for yr = 0 to 360 by 45 do
		(
 
				p = plane pos: [xr,yr,0] lengthsegments:1 widthsegments:1
				gSHsetObjectRotation p xr yr 0
				p = convertToPoly(p)
 
		)
	)
 
fn gSHsetObjectRotation obj rx ry rz =
(
    -- Reset the object's transformation matrix so that 
    -- it only includes position and scale information. 
    -- Doing this clears out any previous object rotation.
    local translateMat = transMatrix obj.transform.pos
    local scaleMat = scaleMatrix obj.transform.scale
    obj.transform = scaleMat * translateMat
 
    -- Perform each axis rotation individually
    rotate obj (angleaxis rx [1,0,0])
    rotate obj (angleaxis ry [0,1,0])
    rotate obj (angleaxis rz [0,0,1])
)

So what I need now are drop angles between 0-90 degrees and heading angles between 0 and 360 degrees. But what I get are angles between 0 and 180 degrees that are obviously not correct.

Could anybody help me with that? I'm really stuck right now.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.