is there something like a 3D Locator in Mathematica 6.0 ?
how could such a thing be realised ?
thx robert
The advantage of a Locator over something like
Manipulate[
Graphics[Point[{x, y}], PlotRange -> 1],
{x, -1, 1}, {y, -1, 1}]
is that it can be directly moved with the mouse. To easily move a point
in 3D, one needs a special input device. If you do have such a device,
then you might want to look at the documentation page
guide/GamepadAndDeviceInterface . It should be possible to use it to
move a point in 3D, but I never had the chance to try this because I do
not have access to game pads.
--
Szabolcs
Best regards
Ingolf Dahl
-----Original Message-----
From: Szabolcs Horv=E1t [mailto:szho...@gmail.com]
Sent: 21 November 2007 12:00
Subject: Re: Locator 3D
roby....@gmail.com wrote:
> Hi everybody,
>
> is there something like a 3D Locator in Mathematica 6.0 ?
> how could such a thing be realised ?
The advantage of a Locator over something like
fun[x_, y_] := x^2 + y^2
DynamicModule[{f, b}, EventHandler[
Show[Plot3D[fun[x, y], {x, -1, 1}, {y, -1, 1}],
Graphics3D[
Dynamic@Quiet@
Check[Sphere[((f - b) t + f) /.
FindRoot[
fun[#1, #2] == #3 & @@ ((f - b) t + f), {t, 0}], .1], {}]],
BoxRatios -> {1, 1, 1}],
{"MouseMoved" :> ({f, b} =
MousePosition["Graphics3DBoxIntercepts"])}]]
Note that sometimes the intersection of the line and surface that is
found by FindRoot[] is outside the visible area.
Szabolcs
On Nov 21, 2007 3:06 PM, Ingolf Dahl <ingol...@telia.com> wrote:
> One could also think of locators with "object snap", in such a way that the
> movement in the 3D case is confined to some graphic elements (points, lines
> or surfaces), present in the 3D graphics. The movement of the locator can
> then be controlled by the 2D position of the mouse in the image plane. But I
> do not know how to implement that in Mathematica in a good way. One could
> maybe imagine working on a freezed(=fixed viewpoint) 2D projection of the 3D
> image, with ordinary 2D locators, and then search the graphics for 3D
> objects with 2D projections in the neighborhood of the locator positions.
> Another possibility is to have two freezed 2D projections from different
> directions, with a common list of 3D locators, coupled to the 2D locators of
> the two projections.
> A third possibility is to use the mouse wheel, available on many mice. But
> how to see where the locator is in the depth direction?
> With all the clever programmers following MathGroup, maybe someone...
>
> Best regards
>
> Ingolf Dahl
>
> -----Original Message-----
> From: Szabolcs Horvát [mailto:szho...@gmail.com]
> Sent: 21 November 2007 12:00
> To: math...@smc.vnet.net
> Subject: Re: Locator 3D
>
> roby....@gmail.com wrote:
> > Hi everybody,
> >
> > is there something like a 3D Locator in Mathematica 6.0 ?
> > how could such a thing be realised ?
>
DynamicModule[{pos = {{0, 0, 0}, {0, 0, 0}}},
EventHandler[
Graphics3D[{Sphere[Dynamic[First@pos], .1]}, PlotRange -> 1],
{"MouseMoved" :> (pos =
MousePosition["Graphics3DBoxIntercepts"])}
]]
(Example "stolen" from the doc page of EventHandler[].)
Szabolcs
On Nov 21, 2007 3:06 PM, Ingolf Dahl <ingol...@telia.com> wrote:
> One could also think of locators with "object snap", in such a way that the
> movement in the 3D case is confined to some graphic elements (points, lines
> or surfaces), present in the 3D graphics. The movement of the locator can
> then be controlled by the 2D position of the mouse in the image plane. But I
> do not know how to implement that in Mathematica in a good way. One could
> maybe imagine working on a freezed(=fixed viewpoint) 2D projection of the 3D
> image, with ordinary 2D locators, and then search the graphics for 3D
> objects with 2D projections in the neighborhood of the locator positions.
> Another possibility is to have two freezed 2D projections from different
> directions, with a common list of 3D locators, coupled to the 2D locators of
> the two projections.
> A third possibility is to use the mouse wheel, available on many mice. But
> how to see where the locator is in the depth direction?
> With all the clever programmers following MathGroup, maybe someone...
>
> Best regards
>
> Ingolf Dahl
>
> -----Original Message-----
> From: Szabolcs Horvát [mailto:szho...@gmail.com]
> Sent: 21 November 2007 12:00
> To: math...@smc.vnet.net
> Subject: Re: Locator 3D
>
> roby....@gmail.com wrote:
> > Hi everybody,
> >
> > is there something like a 3D Locator in Mathematica 6.0 ?
> > how could such a thing be realised ?
>
fun[x_, y_] := Sin[x*Pi]*Sin[y*Pi]
and then is sometimes seems to me as if a background solution is found,
since the sphere disappear.
The ball is passed...
Ingolf Dahl
> -----Original Message-----
> From: Szabolcs Horv=E1t [mailto:szho...@gmail.com]
> Sent: den 21 november 2007 17:06
> To: ingol...@telia.com
> Cc: roby....@gmail.com; math...@smc.vnet.net
> Subject: Re: Re: Locator 3D
>
> Here's a semi-working example for moving a point on a 3D surface:
>
> fun[x_, y_] := x^2 + y^2
>
> DynamicModule[{f, b}, EventHandler[
> Show[Plot3D[fun[x, y], {x, -1, 1}, {y, -1, 1}],
> Graphics3D[
> Dynamic@Quiet@
> Check[Sphere[((f - b) t + f) /.
> FindRoot[
> fun[#1, #2] == #3 & @@ ((f - b) t + f), {t, 0}], .1], {}]],
> BoxRatios -> {1, 1, 1}],
> {"MouseMoved" :> ({f, b} =
> MousePosition["Graphics3DBoxIntercepts"])}]]
>
> Note that sometimes the intersection of the line and surface
> that is found by FindRoot[] is outside the visible area.
>
> > > Hi everybody,
> > >
> > > is there something like a 3D Locator in Mathematica 6.0 ?
> > > how could such a thing be realised ?
> >
Other posters have beaten me to suggesting MousePosition and specifying the
coordinates "Graphics3DBoxIntercepts." This, I think, is the key, but you're
on your own in figuring out how to apply the information to your
application. The approach will be different if you have graphics primitives
or if you have built-up shapes.
I have a background project running in which I'm trying to pick facets from
a shape generated by RegionPlot3D. I'm running an EventHandler inside a
Manipulate (an effort than has its own dark, musty corners in which gotchas
breed and flourish), I'm trying to use MousePosition to get the box
intercepts, use the intercepts to construct a Pluecker line (which would
represent the line perpendicular to the display screen through the mouse
position), disassemble the region into its GraphicsComplex, extract corner
coordinates for each facet, I think I have to construct Pluecker lines for
the edges too, then, just by brute force, find the intersected facet (a
facet for which the moments of all its edge lines about the pick line have
the same sign.) In the process, I think I'll be able to handle multiple
intersections, based on the signs of the moments, but that's some way off.
I wouldn't be able to deal with facets bounded by concave polygons at all,
but I have no idea whatsoever whether RegionPlot3D generates things like
that. All triangles would be good.
So far, it's pretty heavy going, having to chop through gotchas at every
step, and in fact I haven't actually gotten to the point where the real work
starts. No one is paying me to do it, so it looks like a winter background
task.
If any of you have something like this running and you're willing to share
details, I'd love to see how you approach it.
Fred Klingener
It's not Locator, but here's a cut at a way to pick 3D objects with the
mouse. It's based on the idea advanced by others, using the {"MouseDown" :>
({f, b} = MousePosition["Graphics3DBoxIntercepts"])} return on a 3D graphic
inside an EventHandler.
The front and back box intercepts {f, b} can be used to construct a Pluecker
line through the displayed plot range, and interactions and picking can be
implemented with the contents.
The modern standard reference for Pluecker lines (at least in the CG world)
seems to be Shoemake's 1998 notes in the Ray Tracing News:
http://www.acm.org/tog/resources/RTNews/html/rtnv11n1.html.
Unfortunately (AFAIC), Shoemake defined his moment term with a left-hand
rule, and I've switched that to right-hand to inject confusion right at the
start but to save myself grief later.
The following example does about the simplest picking to illustrate the
method. I generate a random point cloud, then pick and highlight individual
points with mouse clicks (using MouseDown instead of MousePosition.)
(* 2008-01-06 Fred Klingener *)
(* Pluecker Line from point Q to point P
use this to construct a Pluecker pick line through the 3D space from the
front and back "Graphics3DBoxIntercepts" *)
pLine[P_, Q_] := {P - Q, Q\[Cross]P}
(* vector from point P normal to Pluecker line L *)
vectorLP[P_, L_] := Module[{U = L[[1]], V = L[[2]]},
U\[Cross](P\[Cross]U - V)/U.U]
(* distance from point P to Pluecker line L *)
distanceLP[P_, L_] := Norm[vectorLP[P, L]];
(* Example - picking random 3D points *)
nPoints = 10;
DynamicModule[{
f = {0.556581, -1.43647, 1.5}
, b = {-1.14868, 1.5, -0.792715}
, cloud =
Table[{RandomReal[{-1, 1}], RandomReal[{-1, 1}],
RandomReal[{-1, 1}]}
, {i, nPoints}]
, d0
, p}
, Column[{
Row[{EventHandler[
image = Graphics3D[{Point[cloud]
, Line[Dynamic@{f, b}]
, {Red, PointSize[0.05],
Dynamic@Point[
p = cloud[[
Position[
d0 = Table[
distanceLP[cloud[[i]], pLine[f, b]], {i, nPoints}],
Min@d0][[1, 1]]]]]}
, Dynamic@Text[ToString[p], p, {-1, 1}]
}
, PlotRange -> {{-1.5, 1.5}, {-1.5, 1.5}, {-1.5, 1.5}}
, Axes -> True
, AxesLabel -> {"x", "y", "z"}
, AspectRatio -> Automatic
, ImageSize -> {300, 300}
] (* Graphics3D *)
, {"MouseDown" :> ({f, b} =
MousePosition["Graphics3DBoxIntercepts"])}
] (* EventHandler *)
, Show[image, ViewPoint -> {2, 2, 2}]
}] (* Row *)
, Row[{Graphics[Text["Picking view.
The pick line is normal to the screen.
The point closest to the pick line is high-lighted.
Click on a point to select it."], ImageSize -> {300, 60}]
, Graphics[
Text["Side view of point field showing point field, selected \
point and pick line.\nThe view can be manipulated with the mouse in \
the usual way"], ImageSize -> {300, 60}]
}]
}] (* Col *)
] (* DynamicModule *)
Pluecker lines have simple relations for picking polygons too, as long as
they're simple enough.
In principle anyway, we should be able to dissect a GraphicsComplex that Mma
generates for more complicated forms (Plot3D, maybe RegionPlot3D, etc.) and
interact with their elements using the Pluecker pick line.
Hth,
Fred Klingener
(1) the cursor within the graphic persists in displaying as two curled
arrows (suggesting rotation); but
(2) there does not seem to be a way to actually rotate the 3D graphic
while the event handler for the mouse is active.
Fred Klingener wrote:
>> <roby....@gmail.com> wrote in message news:fi0ndv$5c5$1...@smc.vnet.net...
>>> Hi everybody,
>>>
>>> is there something like a 3D Locator in Mathematica 6.0 ?
>>> how could such a thing be realised ?
>
> Mathe>matica generates for more complicated forms (Plot3D, maybe
> RegionPlot3D, etc.) and
> interact with their elements using the Pluecker pick line.
>
> Hth,
> Fred Klingener
>
>
--
Murray Eisenberg mur...@math.umass.edu
Mathematics & Statistics Dept.
Lederle Graduate Research Tower phone 413 549-1020 (H)
University of Massachusetts 413 545-2859 (W)
710 North Pleasant Street fax 413 545-1801
Amherst, MA 01003-9305
I think we can get some inspiration from 3D games.
For example, Homeworld. By moving the mouse we are moving the 3D
selection point on X-Y pane, then holding SHIFT down and moving the
mouse to move the selection point on Z axis while (X, Y) are not
changed.
--
Li Zhengji
The cursor behavior is indeed unpleasant (and it gets more unpleasant, to
the point of unusability, and more mysterious if you wrap the example in a
Manipulate. Maybe we'll get to that later.)
I don't know whether it helps or hurts to show the behavior using MouseMoved
in the EventHandler rather than MouseDown:
(* 2008-01-07 Fred Klingener *)
(* 3D Picker with MouseMoved *)
(* Pluecker Line from point Q to point P use this to construct a \
Pluecker pick line through the 3D space from the front and back \
"Graphics3DBoxIntercepts" *)
pLine[P_, Q_] := {P - Q, Q\[Cross]P}
(*vector from point P normal to Pluecker line L*)
vectorLP[P_, L_] :=
Module[{U = L[[1]], V = L[[2]]}, U\[Cross](P\[Cross]U - V)/U.U]
(*distance from point P to Pluecker line L*)
distanceLP[P_, L_] := Norm[vectorLP[P, L]];
nPoints = 10;
DynamicModule[{
f = {0.556581, -1.43647, 1.5}
, b = {-1.14868, 1.5, -0.792715}
, cloud =
Table[{RandomReal[{-1, 1}], RandomReal[{-1, 1}],
RandomReal[{-1, 1}]}
, {i, nPoints}]
, d0
, p}
, Column[{
Row[{EventHandler[
image = Graphics3D[{Point[cloud]
, Line[Dynamic@{f, b}]
, {Red, PointSize[0.05],
Dynamic@Point[
p = cloud[[
Position[
d0 = Table[
distanceLP[cloud[[i]], pLine[f, b]], {i, nPoints}],
Min@d0][[1, 1]]]]]}
, Dynamic@Text[ToString[p], p, {0, 1.5}]
}
, PlotRange -> {{-1.5, 1.5}, {-1.5, 1.5}, {-1.5, 1.5}}
, Axes -> True
, AxesLabel -> {"x", "y", "z"}
, AspectRatio -> Automatic
, ImageSize -> {300, 300}
] (* Graphics3D *)
, {"MouseMoved" :> ({f, b} =
MousePosition["Graphics3DBoxIntercepts"])}
] (* EventHandler *)
, Show[image, ViewPoint -> {2, 2, 2}]
}] (* Row *)
, Row[{Graphics[Text["Picking view.
The pick line is normal to the screen.
The point closest to the pick line is high-lighted.
Click on a point to select it."], ImageSize -> {300, 60}]
, Graphics[
Text["Side view of point field showing point field, selected \
point and pick line.\nThe view can be manipulated with the mouse in \
the usual way"], ImageSize -> {300, 60}]
}]
}] (* Col *)
] (* DynamicModule *)
Here, we get both images mousable and EventHandler active. The selection
snaps to the point closest to the pick line (but the pick line does not snap
to the point). The cursor image over both views is the curly arrows, this
time appropriate because the orientations of both images can be
independently manipulated.
Better? Depends. But it is different, and it feeds my conviction that I
don't have the slightest idea what's going on or how to control it.
Fred
A natural enough approach to manipulating a pick cursor, but the crux here
is relating the resulting 2D screen coordinates to a pick object in
Graphics3D space.
A lot of the work can be done with user-accessible information (like
ViewMatrix), but there seem to be key data hidden. The display changes size
with labeling option e.g.
AFAIK the only place the complete transformation is exposed is in
EventHandler with MousePosition["Graphics3DBoxIntercepts"].
Fred
> is relating the resulting 2D screen coordinates to a pick object in
> Graphics3D space.
>
> A lot of the work can be done with user-accessible information (like
> ViewMatrix), but there seem to be key data hidden. The display changes siz=
e
> with labeling option e.g.
>
> AFAIK the only place the complete transformation is exposed is in
> EventHandler with MousePosition["Graphics3DBoxIntercepts"].
>
> Fred
Mouseover and Tooltip work in 3D as well:
DynamicModule[{i = 0},
Graphics3D[
{AbsolutePointSize[5],
MapIndexed[
Mouseover[Dynamic[i = 0; Point[#]],
Dynamic[
i = #2[[1]]; {AbsolutePointSize[10], Red, Point[#]}]] &,
RandomReal[{-1, 1}, {10, 3}]]},
Epilog -> Inset[Style[Dynamic[i], 24], ImageScaled[{.5, .95}]],
PlotRange -> 1]
]
Maxim Rytin
m...@inbox.ru
Maxim,
That's a nifty solution that works inside a Manipulate as well.
Manipulate[
Graphics3D[{AbsolutePointSize[5],
MapIndexed[
Mouseover[Dynamic[i = 0; Point[#]],
Dynamic[i = #2[[1]]; {AbsolutePointSize[10], Red, Point[#]}]] &,
RandomReal[{-1, 1}, {10, 3}]]},
Epilog -> Inset[Style[Dynamic[i], 24], ImageScaled[{.5, .95}]],
PlotRange -> 1]
, {n, Appearance -> None}
, Initialization :> (i = 0)
]
If we substitute the node list mined from the GraphicsComplex of a graphic
that Mathematica creates, it seems to work ok too.
Here's a surface generated by Plot3D with nodes pickable and their
coordinates shown using a Mouseover. The GraphicsComplex is recovered with
// InputForm, and even though there are some nifty idioms for recovering the
node list, I've just dug out by brute force.
Manipulate[
Show[
img,
Graphics3D[{AbsolutePointSize[5]
, MapIndexed[
Mouseover[
Dynamic[i = 0; {Opacity[0], Point[#]}]
, Dynamic[i = #2[[1]]; {AbsolutePointSize[10], Red, Point[#]
, Text[ToString[NumberForm[#, {3, 2}]], #, {0, -2},
Background -> White]}]
] &, nodeList]}
]
]
, {n, Appearance -> None}
, Initialization :> (
i = 0;
fun[x_, y_] := x^2 + y^2; img = Plot3D[fun[x, y], {x, -1, 1}, {y, -1, 1}
, PlotStyle -> {FaceForm[White], EdgeForm[None]}
, Axes -> True
, AxesLabel -> {"x", "y", "z"}
, PlotPoints -> 2
, Mesh -> None
, NormalsFunction -> None
, AspectRatio -> Automatic
, ImageSize -> {400, 400}
, ViewPoint -> {1.5, -2, 5}];
gc = img // InputForm;
nodeList = gc[[1, 1, 1]];
)
]
There are still some mysteries. The nodes can't be picked if the view angle
is too shallow, and they can't be picked at all from below.
Cheers,
Fred