Table of Contents
Calculate the angle between two points.
C++
See Also
Question
For two sets of 3-D vectors, I use the method demonstrated in Calculate the angle between two vectors to calculate the angle between them. The results for both are always the same - 45 degree in this case. For example:
But the result that I need should be that one is 45 degree the other is 315 degree. How to get the results that I need?
Answer
The following example code demonstrates how to calculate the angle between two 3-D points, given a common base point.
/*
Description: Calculates the angle between two points that lie on a give plane. Parameters: plane - [in] The plane on which the points lie basept - [in] The base point refpt1 - [in] The first reference point refpt2 - [in] The second reference point radians - [out] The angle in radians Returns: TRUE if successful, FALSE otherwise. */ static bool CalculatePlaneAngle( const ON_Plane& plane, const ON_3dPoint& basept, const ON_3dPoint& refpt1, const ON_3dPoint& refpt2, double& radians ) { // Make sure the points are on the plane double tolerance = 0.000001; double dist = 0.0; dist = plane.plane_equation.ValueAt( basept ); if( fabs(dist) > tolerance ) return false; dist = plane.plane_equation.ValueAt( refpt1 ); if( fabs(dist) > tolerance ) return false; dist = plane.plane_equation.ValueAt( refpt2 ); if( fabs(dist) > tolerance ) return false; // Make sure base and reference points are not equal if( basept == refpt1 | basept == refpt2 ) return false; // Calculate angle between vectors ON_3dVector v = refpt2 - basept; v.Unitize(); ON_3dVector zerov = refpt1 - basept; zerov.Unitize(); double dot = ON_DotProduct( zerov, v ); dot = RHINO_CLAMP( dot, -1.0, 1.0 ); double angle = acos( dot ); // Calculate a new y-axis based on the plane's // zaxis and our zero vector v = ON_CrossProduct( plane.zaxis, zerov ); v.Unitize(); // Create a plane using our y-axis a the normal ON_Plane yplane; yplane.CreateFromNormal( basept, v ); // Figure out which size of this plane that refpt2 is on dist = yplane.plane_equation.ValueAt( refpt2 ); if( dist < 0.0 ) angle = (ON_PI * 2.0) - angle; radians = angle; return true; }
You can use the above function as follows:
CRhinoCommand::result CCommandTest::RunCommand( const CRhinoCommandContext& context ) { CRhinoView* view = RhinoApp().ActiveView(); if( 0 == view ) return failure; ON_Plane plane = view->ActiveViewport().ConstructionPlane().m_plane; ON_3dPoint basept, refpt1, refpt2; CRhinoGetPoint gp; gp.SetCommandPrompt( L"Base point" ); gp.Constrain( plane ); gp.GetPoint(); if( gp.CommandResult() != success ) return gp.CommandResult(); basept = gp.Point(); gp.SetCommandPrompt( L"First angle point" ); gp.SetBasePoint( basept ); gp.DrawLineFromPoint( basept, TRUE ); gp.GetPoint(); if( gp.CommandResult() != success ) return gp.CommandResult(); refpt1 = gp.Point(); gp.SetCommandPrompt( L"Second angle point" ); gp.SetBasePoint( basept ); gp.DrawLineFromPoint( basept, TRUE ); gp.GetPoint(); if( gp.CommandResult() != success ) return gp.CommandResult(); refpt2 = gp.Point(); double angle = 0.0; if( CalculatePlaneAngle(plane, basept, refpt1, refpt2, angle) ) RhinoApp().Print( L"Angle = %.3f degrees.\n", angle * (180.0 / ON_PI) ); return success; }
