[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: arcs in 3d?



On Thu, 31 Mar 2005, Jeffrey A. Edlund wrote:

> I'm drawing a figure using epix using arrows in 3d.
>
> arrow(lisa1center,lisa1center-1*lisa1normal); // representing the normal to a triangle in 3d
>
> arrow(lisa1center,lisa1center-(1.0/sqrt(lisa1center|lisa1center))*lisa1center); // arrow pointing towards the origin
>
> I'd like to draw an arc between the 2 arrows an then place a label next
> to the arc to indicate the angle.  Is this possible when neither arrow
> is in the (x1,x2) plane?
>
Hi Jeffrey,

Here are (lightly tested:) functions that

* draw the smaller arc between two arrows in the plane spanned by the
  arrows, assuming the arrows have the same length,

* return a point along said arc, with t=0 corresponding to the first point
  and t=1 to the second.

---(snip)---
// arc joining arrow(center, arg1) and arrow(center, arg2)
void arc_span(P center, P arg1, P arg2)
{
	// construct orthogonal basis of plane spanned
	P v1=arg1-center, v2=arg2-center; // direction vectors
	P perp1 = v2%v1;                  // orthogonalize
	perp1 *= 1/norm(perp1);           // OK if arrows not parallel

	double norm1=norm(v1);
	double norm2=norm(v2);

	double theta=Acos((v1|v2)/(norm1*norm2));

	ellipse(center, v1, norm1*perp1, 0, theta);
}

// generalized midpoint of arc: t=0 <-> arg1, t=1 <-> arg2
P arc_point(P center, P arg1, P arg2, double t=0.5)
{
	P v1=arg1-center, v2=arg2-center;
	P perp1 = v2%v1;
	perp1 *= 1/norm(perp1);

	double norm1=norm(v1);
	double norm2=norm(v2);

	double theta=t*Acos((v1|v2)/(norm1*norm2));

  return center+ Cos(theta)*v1 + (Sin(theta)*norm1)*perp1;
}

---(snip)---
The attached file is a complete figure.

> Another simple question:  If I have a P point, how to I access the
> members of the triple?  i.e. something like point.x point.y point.z?
>
point.x1(), etc. :)

Best, Andy

Andrew D. Hwang			ahwang@mathcs.holycross.edu
Department of Math and CS	http://math.holycross.edu/~ahwang
College of the Holy Cross	(508) 793-2458 (Office: 320 Swords)
Worcester, MA, 01610-2395	(508) 793-3530 (fax)

/* -*-ePiX-*- */
#include "epix.h"
using namespace ePiX;

void arc_span(P center, P arg1, P arg2)
{
  P v1=arg1-center, v2=arg2-center;
  P perp1 = v2%v1;
  perp1 *= 1/norm(perp1);

  double norm1=norm(v1);
  double norm2=norm(v2);

  double theta=Acos((v1|v2)/(norm1*norm2));

  ellipse(center, v1, norm1*perp1, 0, theta);
}

P arc_point(P center, P arg1, P arg2, double t)
{
  P v1=arg1-center, v2=arg2-center;
  P perp1 = v2%v1;
  perp1 *= 1/norm(perp1);

  double norm1=norm(v1);
  double norm2=norm(v2);

  double theta=t*Acos((v1|v2)/(norm1*norm2));

  return center+ Cos(theta)*v1 + (Sin(theta)*norm1)*perp1;
}

P ctr(2,1,0), arg1=ctr+sph(2,-M_PI/6,M_PI_4), arg2=ctr+sph(2,M_PI/8,-M_PI/3);

int main() 
{
  bounding_box(P(-4,-4),P(4,4));
  unitlength("1in");
  picture(6,6);

  begin();

  camera.at(P(5,4,0));

  arrow_fill(1);
  arrow(ctr, arg1, 0.5);
  arrow(ctr, arg2, 0.5);

  dot(arc_point(ctr, arg1, arg2, 0), P(0,4), "A", t);
  dot(arc_point(ctr, arg1, arg2, 0.25), P(-4,0), "B", tl);
  dot(arc_point(ctr, arg1, arg2, 0.5), P(-4,0), "C", l);
  dot(arc_point(ctr, arg1, arg2, 0.75), P(-2,-2), "D", bl);
  dot(arc_point(ctr, arg1, arg2, 1), P(0,-4), "E", b);

  red(); bold();
  arc_span(ctr, arg1, arg2);

  end();
}