Re: How draw 3D Arrows?
- To: mathgroup@smc.vnet.net
- Subject: [mg11306] Re: How draw 3D Arrows?
- From: SChandler <SChandler@uh.edu>
- Date: Wed, 4 Mar 1998 01:40:10 -0500
- Organization: University of Houston
- References: <6dg8gm$2u3@smc.vnet.net>
Terry Harter wrote: > Hi All; > While I realize that the 'Arrow' package of Mathematica can draw > *two-dimensional" arrows, the package fails at giving a 3D arrow. > Anyone have any ideas or suggestions? Say I have 2, distinct 3-dim > points {a,b,c} and {x,y,z}, how do I then draw a 3-dim arrow from > {a,b,c} to {x,y,z} with the "head" of the arrow at {x,y,z}? I could > find nothing on this in MathSource. Many thanks in advance! .....Terry > This issue has come up before. Here are snippets from prior postings on this newsgroup. Seth J. Chandler Associate Professor of Law University of Houston Law Center Snippet 1 Martin Kraus :) (*-------------begin of package, cut here------------------------------------*) (* :Title: Three-Dimensional Arrow Graphics *) (* :Context: Arrow3D` *) (* :Author: Martin Kraus (fn141@fen.baynet.de) *) (* :Summary: This package introduces the functions Arrow3D[start, finish] and ArcArrow3D[center, axis1, axis2] to create three-dimensional (curved) arrows with flat arrowheads. *) (* :Package Version: 1.0.0 (December 97) *) (* :Mathematica Version: 3.0 *) (* :Copyright: Copyright 1997, Martin Kraus*) (* :History: V 0.0 November 1997 *) (* :Keywords: Arrow, Vector, Graphics *) (* :Sources: Arrow.m *) (* :Limitations: *) (* :Discussion: *) BeginPackage["Arrow3D`"] Arrow3D::usage= "Arrow3D[start, finish, (opts)] generates several graphics primitives representing an arrow starting at start and ending at finish. By default there is a arrowhead of length 0, i.e. no arrowhead."; ArcArrow3D::usage= "ArcArrow3D[center, axis1, axis2, (opts)] generates several graphics primitives representing an arc with arrowhead starting at center+axis1 and ending in the direction of center+axis2. By default there is a arrowhead of length 0, i.e. no arrow head."; HeadLength::usage= "HeadLength is an option to Arrow3D and ArcArrow3D. It describes the length of the arrowhead."; HeadWidth::usage= "HeadWidth is an option to Arrow3D and ArcArrow3D. It describes the width of the arrowhead, relative to the length of the arrowhead (specified by HeadLength)."; HeadCenter::usage= "HeadCenter is an option to Arrow3D and ArcArrow3D. It describes the location of the center of the base of the arrowhead along the length of the arrow, as a factor of the length of the arrowhead. That is, if HeadCenter -> 0, the arrow will be two lines; if HeadCenter -> 1, the arrowhead will be a perfect triangle; otherwise, the arrowhead will be four-sided."; HeadTop::usage= "HeadTop is an option to Arrow3D and ArcArrow3D. It describes the location of the top of the arrowhead along the length of the arrow. It may be used to leave some space at the top for a point, specified by HeadPointSize."; HeadPointSize::usage= "HeadPointSize is an option to Arrow3D and ArcArrow3D. It describes the size of a point at the top of the arrow, relative to the width of the whole plot."; HeadBlockWidth::usage= "HeadBlockWidth is an option to Arrow3D and ArcArrow3D. It describes the width of a line at the top of the arrowhead, perpendicular to the arrow."; HeadNormal::usage= "HeadNormal is an option to Arrow3D and ArcArrow3D. It describes the normal direction of the arrowhead."; TailLength::usage= "TailLength is an option to Arrow3D and ArcArrow3D. It works exactly like HeadLength, but for the tail of the arrow"; TailWidth::usage= "TailWidth is an option to Arrow3D and ArcArrow3D. It works exactly like HeadWidth, but for the tail of the arrow"; TailCenter::usage= "TailCenter is an option to Arrow3D and ArcArrow3D. It works exactly like HeadCenter, but for the tail of the arrow"; TailTop::usage= "TailTop is an option to Arrow3D It works exactly like HeadTop, but for the tail of the arrow"; TailPointSize::usage= "TailPointSize is an option to Arrow3D and ArcArrow3D. It works exactly like HeadPointSize, but for the tail of the arrow"; TailBlockWidth::usage= "TailBlockWidth is an option to Arrow3D and ArcArrow3D. It works exactly like HeadBlockWidth, but for the tail of the arrow"; Snippet 2 Appended below is some code written by John Novak from Wolfram Research which does what you want. This has not yet been included in StandardPackages. Cheers, Paul ____________________________________________________________________ Paul Abbott Phone: +61-8-9380-2734 Department of Physics Fax: +61-8-9380-1014 The University of Western Australia Nedlands WA 6907 mailto:paul@physics.uwa.edu.au AUSTRALIA http://www.pd.uwa.edu.au/~paul God IS a weakly left-handed dice player ____________________________________________________________________ (* :Title: Arrow 3D *) (* :Context: Graphics`Arrow3D` *) (* :Author: John M. Novak *) (* :Summary: crude 3D arrow primitive *) (* :Copyright: Copyright 1996 Wolfram Research, Inc. *) (* :Package Version: 1.0 *) (* :Mathematica Version: 3.0 *) (* :History: V1.0 -- March 1996 by John M. Novak *) (* :Keywords: arrow, Graphics3D *) (* :Sources: Tom Wickham-Jones, "Mathematica Graphics" *) (* :Discussion: This is a package to add crude 3D arrows by using 3D graphics primitives. The main problem with this approach is that arrows don't have an optimal appearance, and distinction between (e.g.) arrows point toward vs. away from the user is difficult to make. On the other hand, it is readily implementable, which is far superior to any other approach available at this time. (The PostScript used in 2D arrows won't layer correctly in 3D, nor would 2D primitives; placing 3D planar primitives with the correct orientation has problems with perspective transforms as well as design problems with things like arrows with a small angle w.r.t. the user.) Because of the essentially different approach from 2D arrows, the package is being made independent of the 2D package for the time being. *) BeginPackage["Graphics`Arrow3D`"] Arrow3D::usage = "Arrow3D[start, end] is a 3D graphics primitive representing an arrow in space. The start point and the end point are given as {x, y, z} triplets. Options controlling the length and width of the arrowhead are available." Begin["`Private`"] (* The following routine is based on OrthogonalVectors from Tom Wickham-Jones' Mathematica Graphics book. *) anOrthogonalVector[ norm:{_,_,_}] := Block[{pos, a, b, v1}, pos = If[ VectorQ[ norm, NumberQ], Abs[N[ norm]], norm] ; pos = Sort[ Transpose[ {pos, Range[ 3]}]] ; {pos, a,b} = Map[ Last, pos] ; v1 = ReplacePart[ {0,0,0}, -Part[ norm, a], b] ; ReplacePart[ v1, Part[ norm, b], a] ] normalize[vec_] := vec/Sqrt[vec . vec] (* The following routine 'rotationmatrix' was borrowed from the standard package Graphics`SurfaceOfRevolution`. *) rotationmatrix[axis_,theta_] := Module[{n1,n2,n3}, {n1,n2,n3} = normalize[axis]//N; {{n1^2 + (1 - n1^2) Cos[theta], n1 n2 (1 - Cos[theta]) + n3 Sin[theta], n1 n3 (1 - Cos[theta]) - n2 Sin[theta]}, {n1 n2 (1 - Cos[theta]) - n3 Sin[theta], n2^2 + (1 - n2^2) Cos[theta], n2 n3 (1 - Cos[theta]) + n1 Sin[theta]}, {n1 n3 (1 - Cos[theta]) + n2 Sin[theta], n2 n3 (1 - Cos[theta]) - n1 Sin[theta], n3^2 + (1 - n3^2) Cos[theta]}}//N ] Arrow3D[base:{_,_,_},tip:{_,_,_}, polys_:10, len_:0.8] := {Line[{base, tip}], mycone[tip - base, base, tip, polys, len]} Arrow3D[base:{_,_,_}, tip:{_, _, _}, ___] := Point[base]/;base == tip mycone[vec_, base_, tip_, polys_, len_] := Block[{norm = anOrthogonalVector[vec], theta}, Map[Polygon[Append[#, tip]]&, Partition[Table[base + len vec + (1 - len)/2 norm . rotationmatrix[vec, theta], {theta, 0, 2 Pi, 2 Pi/polys}]//N, 2, 1] ] ] End[] EndPackage[] >