How to output custom polygon coordinates in Mathematica? - wolfram-mathematica

I am trying to make either a nested manipulate or just a manipulate with two windows: I need one window which functions as:
Manipulate[Graphics[Polygon[pt],
PlotRange -> 2], {{pt, {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {1, -1}}},
Locator, LocatorAutoCreate -> True}]
but outputs its coordinates to another window which uses these coordinates to plot a specified graph. I am not sure if Manipulate is even the best option for this, but essentially I am trying to make a visual interface where a user can specify a polygon and then the program uses the information of those coordinates to plot a specified 3D plot.
I think I could figure out how to do this if I knew how to output the coordinates from the manipulate or how to make something that does.

For Example:
GraphicsRow[{
Manipulate[
Graphics[Polygon[rs = pt], PlotRange -> 2],
{{pt, {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {1, -1}}},
Locator, LocatorAutoCreate -> True}],
Dynamic#
ParametricPlot3D[Through[(Interpolation /#
First#(Transpose /# {Append[#, 0] & /# rs}))[t]], {t, 1, Length#rs},
PlotRange -> 2]}]

Related

Effect of change in Viewpoint->{x,y,z} on the size of graphic objects is not what I expected. How to fix?

If you run the following code snippet:
Manipulate[
Graphics3D[
{Cuboid[{{-1, -1, -1}, {1, 1, 1}}], Sphere[{5, 5, 5}, 1]},
ViewPoint -> {1, 1, a}, AxesOrigin -> {0,0,0}
],
{a, 1, 100}
]
and move the viewpoint from (1,1,1) to (1,1,100) with the slider you will see that after a while the objects remain fixed in size.
Questions.
1. When I move the viewpoint further away from the scene I want the objects to become smaller. How should this be done in Mathematica?
( EDIT: )
2. What is the position of the 'camera' in relation to Viewpoint?
See ViewAngle. Under "More Information", note that the default setting ViewAngle -> Automatic is effectively equivalent to ViewAngle -> All when you zoom far enough out.
You just need to add an explicit setting for ViewAngle:
Manipulate[
Graphics3D[{Cuboid[{{-1, -1, -1}, {1, 1, 1}}], Sphere[{5, 5, 5}, 1]},
ViewPoint -> {1, 1, a}, AxesOrigin -> {0, 0, 0},
ViewAngle -> 35 Degree], {a, 1, 100}]
As far as I know, the camera viewpoint really coincides with the position given by ViewPoint. Because Mathematica scales the result to fit in about the same image you don't see much changes but they are there. The perspective changes considerably. Try, for instance, to move away from a semi-transparant square and you'll see that the farther you go, the more the projection becomes an orthogonal projection:
If you want to scale your image according to distance you can use ImageSize. SphericalRegion is good to stabilize the image.
Manipulate[
vp = {1, 1, a};
Graphics3D[{Cuboid[{{-1, -1, -1}, {1, 1, 1}}], Sphere[{5, 5, 5}, 1]},
ViewPoint -> vp,
AxesOrigin -> {0, 0, 0},
SphericalRegion -> True,
ImageSize -> 500/Norm[vp]],
{a, 1, 100}
]
[animation made with some ImagePadding to keep object in the center. I stopped the animation at a = 10, the image gets pretty small after that]

Mathematica: Removing graphics primitives

Given that g is a graphics object with primitives such as Lines and Polygons, how do you remove some of them? To add more primitives to an existing graphics object we can use Show, for instance: Show[g, g2] where g2 is another graphics object with other primitives. But how do you remove unwanted primitive objects? Take a look at the following
ListPlot3D[{{0, 0, 1}, {1, 0, 0}, {0, 1, 0}, {1, 1, 0}}, Mesh -> {1, 1}]
Now, for the input form:
InputForm[
ListPlot3D[{{0, 0, 1}, {1, 0, 0}, {0, 1, 0}, {1, 1, 0}}, Mesh -> {1, 1}]
]
To create a wire frame from this object all we have to do is remove the polygons. As an extra we can also remove the vertex normals since they don't contribute to the wireframe.
Notice that to make a wireframe we can simply set PlotStyle -> None as an option in ListPlot3D. This gets rid of the Polygons but doesn't remove the VertexNormals.
To clarify the question. Given that
g = ListPlot3D[{{0, 0, 1}, {1, 0, 0}, {0, 1, 0}, {1, 1, 0}}, Mesh -> {1, 1}]
How do you remove some of the of the graphics primitives from g and how do you remove some of the options, i.e. VertexNormals? Note: option VertexNormals is an option of GraphicsComplex.
If this is not possible then maybe the next question would be, how do you obtain the data used to generate g to generate a new graphics object with some of the data obtained from g.
One way is to use transformation rules. Given your
im = ListPlot3D[{{0, 0, 1}, {1, 0, 0}, {0, 1, 0}, {1, 1, 0}}, Mesh -> {1, 1}]
You can do
newim = im /. {_Polygon :> Sequence[], (VertexNormals -> _) :> Sequence[]}
or, more compactly using Alternatives:
newim = im /. _Polygon | (VertexNormals -> _) :> Sequence[]
You could also use DeleteCases to get a similar effect:
newim = DeleteCases[im, (_Polygon | (VertexNormals -> _)), Infinity]

How to make a grid of plots with a single pair of FrameLabels?

What is the simplest way to create a row/column/grid of plots, with the whole grid having a single FrameLabel?
I need something similar to this:
p := ListPlot[RandomInteger[10, 5], Joined -> True, Axes -> False,
Frame -> True, PlotRange -> {0, 11},
FrameLabel -> {"horizontal", None}, AspectRatio -> 1]
GraphicsRow[{Show[p, FrameLabel -> {"horizontal", "vertical"}], p, p}]
For a row format, it could have one or multiple horizontal labels, but only one vertical one.
Issues to consider:
Vertical scale must match for all plots, and must not be ruined by e.g. a too long label or automatic PlotRangePadding.
Good (and resize-tolerant!) control of inter-plot spacing is needed (after all, this is one of the motivations behind removing the redundant labels)
General space-efficiency of the arrangement. Maximum content, minimum (unnecessary) whitespace.
EDIT
I'm trying to be able to robustly create print ready figures, which involves a lot of resizing. (Because the exported PDFs will usually not have the same proportions as what I see in the notebook, and must have readable but not oversized fonts)
You can use LevelScheme to achieve what you want. Here's an example:
<< "LevelScheme`"
Figure[{
Multipanel[{{0, 1}, {0, 1}}, {1, 3},
XFrameLabels -> textit["x"], BufferB -> 3,
YFrameLabels -> textit["Sinc(x)"], BufferL -> 3,
TickFontSize -> 9,
XGapSizes -> {0.1, 0.1},
PanelLetterCorner -> {1, 1}
],
FigurePanel[{1, 1}, PlotRange -> {{-1.6, -0.6}, {-0.5, 1}}],
RawGraphics[Plot[Sinc[20 x], {x, -1.6, -0.6}]],
FigurePanel[{1, 2}, PlotRange -> {{-0.5, 0.5}, {-0.5, 1}}],
RawGraphics[Plot[Sinc[20 x], {x, -0.5, 0.5}]],
FigurePanel[{1, 3}, PlotRange -> {{0.6, 1.6}, {-0.5, 1}}],
RawGraphics[Plot[Sinc[20 x], {x, 0.6, 1.6}]]
},
PlotRange -> {{-0.1, 1.02}, {-0.12, 1.095}}]
LevelScheme offers you tremendous flexibility in the arrangement of your plot.
Instead of naming giving the plot common labels, you can move the definition inside the FigurePanel[] and control the labels for each one individually.
You can set inter-plot spacings both in the X and Y directions and also change the sizes of each panel, for e.g., the left one can take up 2/3 of the space and the next two just 1/6 of the space each.
You can set individual plot ranges, change the frame tick labels for each, control which side of the panel (top/bottom/l/r) the labels should be marked, change panel numberings, etc.
The only drawback is that you might have to wrestle with it in some cases, but in general, I've found it a pleasure to use.
EDIT
Here's one similar to your example:
Figure[{
Multipanel[{{0, 1}, {0, 1}}, {1, 3},
YFrameLabels -> textit["Vertical"], BufferL -> 3,
TickFontSize -> 9,
XGapSizes -> {0.1, 0.1},
PanelLetterCorner -> {1, 1}
],
FigurePanel[{1, 1}, PlotRange -> {{1, 10}, {0, 10}}],
RawGraphics[ListLinePlot[RandomInteger[10, 10]]],
FigurePanel[{1, 2}, PlotRange -> {{1, 10}, {0, 10}},
LabB -> textit["Horizontal"], BufferB -> 3],
RawGraphics[ListLinePlot[RandomInteger[10, 10]]],
FigurePanel[{1, 3}, PlotRange -> {{1, 10}, {0, 10}}],
RawGraphics[ListLinePlot[RandomInteger[10, 10]]]
},
PlotRange -> {{-0.1, 1.02}, {-0.2, 1.095}}]
EDIT 2
To answer Mr. Wizard's comment, here's a blank template for a 2x3 grid
Figure[{Multipanel[{{0, 1}, {0, 1}}, {2, 3},
XFrameTicks -> None,
YFrameTicks -> None,
XGapSizes -> {0.1, 0.1},
YGapSizes -> {0.1}],
FigurePanel[{1, 1}],
FigurePanel[{1, 2}],
FigurePanel[{1, 3}],
FigurePanel[{2, 1}],
FigurePanel[{2, 2}],
FigurePanel[{2, 3}]
}, PlotRange -> {{-0.01, 1.01}, {-0.01, 1.01}}]
And here's one with extended panels
Figure[{Multipanel[{{0, 1}, {0, 1}}, {2, 3},
XFrameTicks -> None,
YFrameTicks -> None,
XGapSizes -> {0.1, 0.1},
YGapSizes -> {0.1}],
FigurePanel[{1, 1}, PanelAdjustments -> {{0, 0}, {1.1, 0}}],
FigurePanel[{1, 2}],
FigurePanel[{1, 3}],
FigurePanel[{2, 2}, PanelAdjustments -> {{0, 1.1}, {0, 0}}]
}, PlotRange -> {{-0.01, 1.01}, {-0.01, 1.01}}]
You already know how to handle multiple horizontal labels through ListPlot.
You can get single labels by using Panel. For example...
p := ListPlot[RandomInteger[10, 5], Joined -> True, Axes -> False,
Frame -> True, PlotRange -> {0, 11}, AspectRatio -> 1]
Panel[GraphicsRow[{p, p, p}], {"horizontal",Rotate["vertical", Pi/2]},
{Bottom, Left}, Background -> White]
You can optionally include labels on Top and Right edges too.
Here is one option I just put together. Its advantage is that it is simple.
I like the look of yoda's LevelScheme plots better, assuming those can be done for a grid as well.
p := ListPlot[RandomInteger[10, 5], Joined -> True, Axes -> False,
Frame -> True, PlotRange -> {0, 11}, AspectRatio -> 1]
gg = GraphicsGrid[{{p, p, p}, {p, p, p}, Graphics /# Text /# {"Left", "Center", "Right"}},
Spacings -> 5, ItemAspectRatio -> {{1, 1, 0.15}}];
Labeled[gg, Rotate["vertical", Pi/2], Left]

Locator goes out of the graph region

When I run the following code
pMin = {-3, -3};
pMax = {3, 3};
range = {pMin, pMax};
Manipulate[
GraphicsGrid[
{
{Graphics[Locator[p], PlotRange -> range]},
{Graphics[Line[{{0, 0}, p}]]}
}, Frame -> All
],
{{p, {1, 1}}, Locator}
]
I expect the Locator control to be within the bounds of the first Graph, but instead it can be moved around the whole GraphicsGrid region. Is there an error in my code?
I also tried
{{p, {1, 1}}, pMin, pMax, Locator}
instead of
{{p, {1, 1}}, Locator}
But it behaves completely wrong.
UPDATE
Thanks to everyone, this is my final solution:
Manipulate[
distr1 = BinormalDistribution[p1, {1, 1}, \[Rho]1];
distr2 = BinormalDistribution[p2, {1, 1}, \[Rho]2];
Grid[
{
{Graphics[{Locator[p1], Locator[p2]},
PlotRange -> {{-5, 5}, {-5, 5}}]},
{Plot3D[{PDF[distr1, {x, y}], PDF[distr2, {x, y}]}, {x, -5, 5}, {y, -5, 5}, PlotRange -> All]}
}],
{{\[Rho]1, 0}, -0.9, 0.9}, {{\[Rho]2, 0}, -0.9, 0.9},
{{p1, {1, 1}}, Locator},
{{p2, {1, 1}}, Locator}
]
UPDATE
Now the problem is that I cannot resize and rotate the lower 3d graph. Does anyone know how to fix that?
I'm back to the solution with two Slider2D objects.
If you examine the InputForm you'll find that GraphicsGrid returns a Graphics object. Thus, the Locator indeed moves throughout the whole image.
GraphicsGrid[{{Graphics[Circle[]]}, {Graphics[Disk[]]}}] // InputForm
If you just change the GraphicsGrid to a Grid, the locator will be restricted to the first part but the result still looks a bit odd. Your PlotRange specification is a bit strange; it doesn't seem to correspond to any format specified in the Documentation center. Perhaps you want something like the following.
Manipulate[
Grid[{
{Graphics[Locator[p], Axes -> True,
PlotRange -> {{-3, 3}, {-3, 3}}]},
{Graphics[Line[{{0, 0}, p}], Axes -> True,
PlotRange -> {{-3, 3}, {-3, 3}}]}},
Frame -> All],
{{p, {1, 1}}, Locator}]
LocatorPane[] does a nice job of confining the locator to a region.
This is a variation on the method used by Mr. Wizard.
Column[{ LocatorPane[Dynamic[pt3],
Framed#Graphics[{}, ImageSize -> 150, PlotRange -> 3]],
Framed#Graphics[{Line[{{-1, 0}, Dynamic#pt3}]}, ImageSize -> {150, 150},
PlotRange -> 3]}]
I would have assumed that you'd want the locator to share the space with the line it controls. In fact, to be "attached" to the line. This turns out to be even easier to implement.
Column[{LocatorPane[Dynamic[pt3],Framed#Graphics[{Line[{{-1, 0}, Dynamic#pt3}]},
ImageSize -> 150, PlotRange -> 3]]}]
I am not sure what you are trying to achieve. There are a number of problems I see, but I don't know what to address. Perhaps you just want a simple Slider2D construction?
DynamicModule[{p = {1, 1}},
Column#{Slider2D[Dynamic[p], {{-3, -3}, {3, 3}},
ImageSize -> {200, 200}],
Graphics[Line[{{0, 0}, Dynamic[p]}],
PlotRange -> {{-3, 3}, {-3, 3}}, ImageSize -> {200, 200}]}]
This is a reply to the updated question about 3D graphic rotation.
I believe that LocatorPane as suggested by David is a good way to approach this. I just put in a generic function since your example would not run on Mathematica 7.
DynamicModule[{pt = {{-1, 3}, {1, 1}}},
Column[{
LocatorPane[Dynamic[pt],
Framed#Graphics[{}, PlotRange -> {{-5, 5}, {-5, 5}}]],
Dynamic#
Plot3D[{x^2 pt[[1, 1]] + y^2 pt[[1, 2]],
-x^2 pt[[2, 1]] - y^2 pt[[2, 1]]},
{x, -5, 5}, {y, -5, 5}]
}]
]

How do I control the appearance of a Locator inside a Mathematica's Manipulate statement?

If I have a Manipulate statement, such as:
Manipulate[
Graphics[Line[{{0, 0}, pt}], PlotRange -> 2], {{pt, {1, 1}},
Locator}]
How do I change the appearance of the Locator object in the easiest way possible? Do I have to resort to Dynamic statements? Specifically, I would have liked to make the Locator invisible.
In addition to WReach's answer: In a normal Locator call its appearance can be given as one of the arguments. When used in a Manipulate this is not possible. However, Appearance can be used to draw other locator symbols.
a = Graphics[{Red, Table[Circle[{0, 0}, i], {i, 3}]}, ImageSize -> 20];
Manipulate[
Graphics[Line[{{0, 0}, pt}], PlotRange -> 2], {{pt, {1, 1}}, Locator,
Appearance -> a}]
I don't think this is documented. Last year I tried finding out how to do this, but couldn't find a way. Got no response on my question on the mathematica newsgroup either.
Try adding Appearance -> None to the Locator control:
Manipulate[
Graphics[
Line[{{0, 0}, pt}]
, PlotRange -> 2
]
, {{pt, {1, 1}}, Locator, Appearance -> None}
]

Resources