Graphics3D refinement for intersection of cone and line - image

Encouraged by this question, I dare to ask something similar.
I am trying to plot with mathematica a cone which is intersected by a line. The start point of the line is on the lateral surface of the cone and its endpoint inside of the cone.
As long as the endpoint of the line is far away from the tip of the cone, everything looks quite nice (use e.g. endpointOfLine = 0.007 in my example). But if the endpoint approaches the tip (endpointOfLine < 0.007 in my example), it seems that a big part of the line would be on the surface of the cone.
Sure, for endpoint values which are very close to the cone tip, the line is almost parallel to the surface so that this effect has probably to appear. But the effect appears also if the endpoint is not so close to cone tip.
Here the example:
totalLength = 10^-2;(*length of the cone*)
theta = 17*10^-3;(*half opening angle of the cone*)
radius[theta_, l_] := Tan[theta]*l;(*radius of the cone as function of its length*)
endpointOfLine = 0.0015;(*endpoint of the test line, to be varied*)
testLine = Line[{{radius[theta, totalLength], 0, totalLength},{0, 0, endpointOfLine}},
VertexColors -> {Orange, Orange}
];
Graphics3D[
{
{
RevolutionPlot3D[{radius[theta, l], 0, l}, {l, 0, totalLength},
Mesh -> None,
PlotStyle -> Directive[Opacity[0.5], Gray],
PlotPoints -> 60][[1]]
},
{testLine}
},
Boxed -> True,BoxRatios -> {1, 1, 3},
Lighting -> None(*ugly, but makes the problem well visible*)
]
Is there any way to reduce this effect? Increasing the PlotPoints to 60 has reduced the effect a bit, but I would be happy if I could reduce it more. Any ideas?

Try to place the endpoint at the base of the cone close but not on the radius like:
testLine =
Line[{{0.97 radius[theta, totalLength], 0, totalLength}, {0, 0, endpointOfLine}},
VertexColors -> {Orange, Orange}
];
I feel this is not a problem fundamentally different from the one you were referring to.

Related

Can't solve Coulomb Force differential equation in Mathematica

I'm trying to solve a problem: I have to find the trajectory of an electron in a graphene lattice using Mathematica. I've tried to solve the Coulomb Force equation with NDSolve and to plot the result for each direction, but i obtain a white plot. Could someone help me please? Thank you in advance. Here's the code for the x direction:
coordx = {0.6327, 1.88058, 3.03927, 4.28716, 5.44584, 6.69373,
7.85241, 9.10029, 1.9728, 3.22069, 4.37937, 5.62726, 6.78594,
8.03382, 9.19251, 10.4404, 3.3129, 4.56079, 5.71947, 6.96736,
8.12604, 9.37393, 10.53261, 11.7805, 4.653, 5.90089, 7.05956,
8.30746, 9.46614, 10.71403, 11.87271, 13.1206};
me = 9.01*10^-31;
pi = 3.14159;
epsilon0 = 8.854*10^-12;
q = -1.6*10^-19;
Q = 1.6*10^-19;
step = 0.01;
Forzax[p_, r_] :=
Sum[(Q*q)/(4 pi*epsilon0*Norm[r - p[[i]]]^2), {i, Length[p]}]
Forzax[coordx, {x[t]}];
NDSolve[{x''[t] == Forzax[coordx, {x[t]}]/me , x[0] == 0,
x'[0] == 0}, {x[t]}, {t, 0, 1500}]
Show[ParametricPlot[Evaluate[{x[t]} /. %], {t, 0, 1500},
PlotRange -> All]]
I don't know what you're trying to plot, but these few modifications seem to plot your function.
sol = NDSolve[{x''[t] == Forzax[coordx, {x[t]}]/me,
x[0] == 0, x'[0] == 0}, {x}, {t, 0, 1500}];
f = sol[[1, 1, 2]];
Plot[f[t], {t, 0, 1500}, PlotRange -> All]
From what I can tell, your code is running fine but the plot is empty because you're calling ParametricPlot with just one function. From the documentation, this is how you call ParametricPlot:
ParametricPlot[{fx[t], fy[t]}, {t, tmin, tmax}]
Since you're still solving the 1D problem and only have x[t], ParametricPlot cannot draw anything; it's missing the y coordinate of the trajectory. Once you do a 2D calculation, ParamatricPlot should be able to give you to figure you want. If you want to do a 3D calculation, you should use ParamatricPlot3D.
A question though: how do you intend to to a 3D calculation of an electron in graphene? The motion of the electron in the 3rd dimension will not follow Newtonian mechanics at all because it is confined so much in that direction. In fact, I'd be kind of cautious about using Newton's 2nd law in graphene no matter what, since electrons in graphene behave like massless particles. I leave the interpretation of the results up to you, but the physicist in me cannot resist adding this word of caution.

Parametrizing 3D geometry for shape optimization

I am trying to parametrize a 3D geometry for shape optimization. The structure looks like the following. Another real example is here.
Currently I am using BSplines to create the lower part and using symmetry to create the whole down part of the foil. Here is what I get.
Now I have many control points to take care in order to run a shape optimization. I also don't know how to join the upper part with the bottom hydrofoil part in a sensible way. I don't know how to design a good middle part of the foil (fat nose part of the foil) where the upper part is linked to. I also need to accompany a flap with in the geometry.
Please offer some suggestion for parametrization of such a surface so that we can manipulate the geometry from MMA. The less control points are there better the situation is for optimization. May be combination of some analytic function in 3D. But I doubt if that is possible.
BR
I think you have two choices: 1) create the second part of the geometry and then write a face-face intersection algorithm to merge them. 2) create the second part of the geometry and write two functions that return -1 if a query point is inside the geometry and +1 if it is out side (other values will do). Then use RegionPlot3D[ f1[x,y,z]<0 || f2[x,y,z]<0,....]. The idea is the to extract the GraphicsComplex and use that. The question is going to be how well you can approximate the corners with that. Here is an illustration of what I mean.
if1[x_, y_, z_] := If[x^2 + y^2 + z^2 <= 1, -1, 1]
if2[x_, y_, z_] := If[(x - 1)^2 + y^2 <= 1 && -1.5 <= z <= 1.5, -1, 1]
res = RegionPlot3D[
if1[x, y, z] < 0 || if2[x, y, z] < 0, {x, -2, 2}, {y, -2,
2}, {z, -2, 2}, PlotPoints -> 100, Boxed -> False, Axes -> False]
Then extract the coords and the polygons.
coords = res[[1, 1]];
poly = Cases[res[[1]], _Polygon, Infinity];
Graphics3D[GraphicsComplex[coords, poly], Boxed -> False]
Hope this helps.

ViewVector transition between two spherical coordinates on a globe

Continuing with the project I previously described I am currently building an animation showing movement between a list of cities. My current code renders a list of cities and makes a set of great circle arcs connecting the cities. The list of cities are part of a timeline so after visiting one city the animation will transition to be centered upon the next.
To my mind this means the ViewVector should be adjusted to show points between a starting city and an ending city. The resulting would probably look like an in-flight map for a long-haul flight sped up considerably. A single frame might look like the following manually produced still:
I now understand how to position the ViewVector above the most recent city but I am quite unsure about how to move the camera smoothly between two spherical coordinate points. My current code is below:
SC[{lat_, lon_}] := {Cos[lon \[Degree]] Cos[lat \[Degree]],
Sin[lon \[Degree]] Cos[lat \[Degree]], Sin[lat \[Degree]]};
GreatCircleArc[{lat1_, lon1_}, {lat2_, lon2_}] :=
Module[{u = SC[{lat1, lon1}], v = SC[{lat2, lon2}], a},
a = VectorAngle[u, v];
Table[Evaluate[RotationTransform[\[Theta], {u, v}][u]], {\[Theta],
0, a, a/Ceiling[10 a]}]]
CityGraphic[name_] := {Opacity[0.85], Black, PointSize[Medium], White,
PointSize[0.045], Point[1.01 SC[CityData[name, "Coordinates"]]]}
CityGraph[places_, age_] :=
Graphics3D[{
Opacity[0.75],
Sphere[{0, 0, 0}, 0.99 ],
Map[Line[
Map[SC,
CountryData[#, "SchematicCoordinates"], {-2}]] &,
CountryData["Countries"]],
Map[CityGraphic, places],
Text[Style[age, FontFamily -> "Helvetica"],
1.02 SC[CityData[First[places], "Coordinates"]]],
White, Line
[Apply[GreatCircleArc,
Partition[Map[CityData[#, "Coordinates"] &, places], 2, 1], {1}]]
},
ViewVector -> {
4 SC[CityData[First[places], "Coordinates"]], {0, 0, 0}},
Boxed -> False,
SphericalRegion -> True,
ImageSize -> {640, 480}
];
CityGraph[{"Tokyo", "Dublin", "Cape Town", "Seattle", "Denver"}, "04"]
In computer graphics people often use Quaternions to smoothly interpolate between various camera viewing directions. Mathematica has a Quaternion package which you could use for basic Quaternion arithmetic. A conversion between Quaternions and Euler angles is described here.
The interpolation process is described here.

Slow ListPlot with PlotMarkers

I am doing this:
ClearAll[matrix];
matrix[p_,q_,nu_:0]:=Module[{sigma},
sigma=p/q;
N#SparseArray[
{{m_,m_}\[Rule]2Cos[2\[Pi]*m*p/q+nu],{i_,j_}/;
Abs[i-j]\[Equal]1\[Rule]1},{q,q}]]
ClearAll[attachsigma]
attachsigma[sigma_,lst_]:={sigma,#}&/#lst
and then execute
fracs = Table[p/q, {q, 2, 30}, {p, 2, q}] // Flatten // DeleteDuplicates;
pq = {Numerator##, Denominator##} & /# fracs;
(ens = Eigenvalues[#] & /#
Normal /# (matrix[#[[1]], #[[2]]] & /# pq);) // Timing
pts = Flatten[#, 1] &#MapThread[attachsigma, {fracs, ens}];
and finally I plot the points as follows (here is the real point of the question):
plot = ListPlot[pts,
PlotMarkers \[Rule] Graphics[{PointSize[Tiny], Point[{0, 0}]}]]
Calculating all the points takes around around 2.6s on my machine, but the plot takes around 25s. If, on the other hand, I plot it like this
ListPlot[pts]
then it is almost instantaneous, as it should (it's just 5256 points). So, it seems PlotMarkers slows things down immensely.
Could anybody
a) explain why (this much I vaguely understand, in analogy with what happens to Sort if you give it custom ordering function) and, more importantly,
b) explain how to avoid this slowdown? I am trying to create plots with quite a bit more points than this so they're really slow; in addition, I am creating lots of them (a movie actually).
One solution would be to not plot all of them, but as I vary parameters it becomes nontrivial to find out which I should include and which not (this would of course work if I only needed this one frame). So, I'd like to speed up the plot creation without removing points.
EDIT: Answered after hints from Sjoerd:
ListPlot[pts] /. Point[List[x___]] \[RuleDelayed] {PointSize[Tiny], Point[List[x]]}
produces the right thing instantaneously. This simply replaces the Points inside the Graphics structure by smaller points by hand.
Now one can increase the upper limit in the table in fracs = Table[p/q, {q, 2, 30}, {p, 2, q}] // Flatten // DeleteDuplicates to 80 or so to get many more points (this thing is the Hofstadter butterfly, and it's a fractal):
PlotMarkers is meant for data plots that contain relatively few points. It is very useful in plots in which you use the markers to identify various conditions. Each individual marker is an Inset as follows:
Inset[Graphics[List[Hue[0.67`,0.6,0.6`],PointSize[Tiny],Point[List[0, 0]]]],10512].
You can imagine this takes up some time and memory.
I also found what seems to be a bug. The plot with PlotMarkers is structured as GraphicsComplex[pointlist,graphicsinstructions]. This point list seems to contain the points in the plot twice!
In[69]:= pts // Length
Out[69]= 5256
In[66]:= plot[[1, 1]] // Length
Out[66]= 10512
In[64]:= Union[plot[[1, 1]]] == Union[pts]
Out[64]= True
In[68]:= Tally[plot[[1, 1]]][[All, 2]] // Mean (*the average number each point occurs*)
Out[68]= 2
Personally, I prefer Graphics to ListPlot, especially when the number of points is large.
Graphics[{Hue[{2/3, 1, 1, .5}], AbsolutePointSize[1.5], Point#pts},
PlotRange -> {{0, 1}, {-4, 4}}, Axes -> False,
AspectRatio -> 1/GoldenRatio]
gives, for example:
Length#pts
102969
I believe the solution you appended to your question can be simplified:
ListPlot[pts] /. x_Point :> {PointSize[Tiny], x}
I voted for both prior answers, but I agree with TomD on the direct use of Graphics.

animate 3d plot with some further requirements in mathematica

I posted at this post before, but I still could not solve the following problem completely. As an example:
{pA, pB, pC, pD} = {{0, 0, Sqrt[61/3]}, {Sqrt[7], 4*Sqrt[2/3], 0}, {0, -5*Sqrt[2/3], 0}, {-Sqrt[71], 4*Sqrt[2/3], 0}};
axis={1,0,0};pt={0,1,0};
plotPolygon[{a_, b_, c_}] := {Opacity[.4], Polygon[{a, b, c}]};
graph=Graphics3D[{plotPolygon[{pA, pB, pC}], plotPolygon[{pA, pB, pD}],
plotPolygon[{pB, pC, pD}], plotPolygon[{pA, pC, pD}]},
Axes -> True, AxesOrigin->pt];
Animate[graph/.gg : Graphics3D[___] :> Rotate[gg, theta, axis], {theta, 0., 2.*Pi}]
I want to rotate along an axis axis={1,0,0} which passes the point pt={0,1,0}. But I don't know how to specify the point information. Also the rotation animation seems very chaotic in the sense that I would expect at least one point (in this case, the origin?) is not rotating.
You need to first change the origin of vertices of your polygon, rotate, and translate back. You can do this by hand
(RotationMatrix[theta,axis].(#-pt) + pt)& /# {pA, pB, pC, pD}
Or, you can combine the transformations using Composition
Composition[
AffineTransform[{RotationMatrix[theta,axis],pt}],TranslationTransform[-pt]
] /# {pA, pB, pC, pD}
Or, you can take the previous composition and apply it directly to your Graphics object
GeometricTransformation[ <graphics>, Composition[ ... ]]
This documentation gives a thorough list of what can be done.
Edit: Here's a working animation script
Animate[
graph /. Graphics3D[prims__, opts : OptionsPattern[]] :>
Graphics3D[
GeometricTransformation[prims,
Composition[
AffineTransform[{RotationMatrix[theta, axis], pt}],
TranslationTransform[-pt]
]
],
opts
],
{theta, 0., 2.*Pi}
]
There's a couple of things to note here. First, GeometricTransformation only appears to work on the primitives themselves, so I had to split out the primitives from the options in Graphics3D via the rule Graphics3D[prims__, opts : OptionsPattern[]]. Also, the transformation itself needs to be within Animate to use the local version of theta.

Resources