Plot3D: drawing points when crossing the grid

I want to draw points at the visible intersections of the grid, for example:

Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}, Mesh -> {1, 4}, Boxed -> False] 

Required Conclusion:

enter image description here

I could calculate where the Mesh would be based on PlotRange and the power of the Mesh and draw the dots there, but I think there should be a simpler alternative way.

A big plus is the ability to select a dot color based on the value of the function. In addition, marking the dots will be wonderful.

Any ideas?

+8
wolfram-mathematica
source share
4 answers

For what it's worth, I also like the simple solution. In addition, it is easy to use the same paint function for both the surface and the dots:

 g = Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}, Mesh -> {1, 4}, Boxed -> False, ColorFunction -> "Rainbow"]; p = ListPointPlot3D[Table[{x, y, Sin[x + y^2]}, {x, -3, 3, (3 - (-3))/(1 + 1)}, {y, -2, 2, (2 - (-2))/(4 + 1)}], ColorFunction -> "Rainbow", PlotStyle -> PointSize[Large]]; Show[g, p] 

enter image description here

Edit: If we want to do this in custom myPlot3D, I think the following:

 myPlot3D[f_, {x_, xmin_, xmax_}, {y_, ymin_, ymax_}, Mesh -> {i_Integer, j_Integer}, opts : OptionsPattern[]] := Module[{g = Plot3D[f, {x, xmin, xmax}, {y, ymin, ymax}, Mesh -> {i, j}, Evaluate@FilterRules[{opts}, Options[Plot3D]]], stx = (xmax - xmin)/(i + 1), sty = (ymax - ymin)/(j + 1), pts}, pts = ListPointPlot3D[ Table[{x, y, f}, {x, xmin + stx, xmax - stx, stx}, {y, ymin + sty, ymax - sty, sty}], Evaluate@FilterRules[{opts}, Options[ListPointPlot3D]]]; Show[g, pts]]; 

Note that the parameters apply to both charts, but are filtered first. I also deleted the points on the plot outline. For example,

 myPlot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}, Mesh -> {4, 10}, Boxed -> False, ColorFunction -> "Rainbow", Axes -> False, PlotStyle -> PointSize[Large]] 

will result in

enter image description here

+8
source share

Here's a very hacky approach: take the mesh lines at the exit and find the intersections. This is quite doable since the output is GraphicsComplex .
First, find the indices of the grid points in the graphical complex:

 g=Plot3D[Sin[x+y^2],{x,-3,3},{y,-2,2},Mesh->{1,4},Boxed->False]; meshlineptindices=First/@Cases[g, _Line, Infinity] 

Now go through the pairs and find the intersections. The following uses NestWhile to recursively view all pairs (first row, other row) for shorter and shorter subscriptions of the original grid list. Received intersections are returned via Sow :

 intesectionindices= Flatten@Reap@NestWhile[( Sow@Outer[Intersection,{First[#]},Rest[#],1]; Rest[#] )&, meshlineptindices, Length[#]>0&] Out[4]= {1260,1491,1264,1401,1284,1371,1298,1448,1205,1219,1528,1525,1526,1527} 

Check out the indices in GraphicsComplex :

 intesections = Part[g[[1,1]],intesectionindices] Out[5]= {{-3.,-1.2,-0.997667},{3.,-1.2,-0.961188},<...>,{0.,1.2,0.977754}} 

Finally, show the dots along with the original graphics:

 Show[g,Graphics3D[{Red,PointSize[Large],Point[intesections]}]] 

output graphics

NTN

Refresh . To get the colored dots, you can simply use

 Graphics3D[{PointSize[Large],({colorfunction[Last@#],Point[#]}&)/@intesections]}] 
+5
source share

Well, Janus beat me to write an answer. I could not understand the part of using the Part. In any case, this is a simplified version:

 g = Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}, Mesh -> {1, 4}, Boxed -> False]; index = Cases[Cases[g, _Line, \[Infinity]], _Integer, \[Infinity]]; inter = Part[Select[Tally@index, Part[#, 2] > 1 &], All, 1]; Show[g, Graphics3D[{Red, PointSize[Large], Point[Part[g[[1, 1]], inter]]}]] 

Image output

Update:

If you only need grid intersections, you need to remove the points that are on the border. Here I make 4 4 ​​mesh.

 g = Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}, Mesh -> {4, 4}, Boxed -> False]; index = Cases[Cases[g, _Line, \[Infinity]], _Integer, \[Infinity]]; inter = Part[Select[Tally@index, Part[#, 2] > 1 &], All, 1]; range = AbsoluteOptions[g, PlotRange][[1]][[2]]; interior = Select[ Part[g[[1, 1]], inter], IntervalMemberQ[Interval[range[[1]]]*0.9999, Part[#, 1]] && IntervalMemberQ[Interval[range[[2]]]*0.9999, Part[#, 2]] & ]; Show[g, Graphics3D[{Red, PointSize[Large], Point[interior] }]] 

Interior points

+4
source share

Whenever possible, I prefer not to interfere with the FullForm graphics. So, going into my original lines, almost the same as FelixCQ, and tried to get a generic function.

 Options[myPlot3D] = Options[Plot3D]; myPlot3D[f_, p__] := Module[ {g = Plot3D[f, p], (*Get the Mesh Divisions*) m = Flatten@Cases[{p}, HoldPattern[Rule[Mesh, r_]] -> r], stx, sty}, (*Get PlotRange*) pr = (List @@@ Options[g, PlotRange])[[1, 2]]; (*Get Mesh steps*) stx = (pr[[1, 2]] - pr[[1, 1]])/(First@m + 1); sty = (pr[[2, 2]] - pr[[2, 1]])/(Last@m + 1); (*Generate points*) pts = Point[ Flatten[Table[{a, b, f /. {x -> a, y -> b}}, {a, pr[[1, 1]] + stx, pr[[1, 2]] - stx, stx}, {b, pr[[2, 1]] + sty, pr[[2, 2]] - sty, sty}], 1]]; Show[g, Graphics3D[{PointSize[Large], pts}]] ]; myPlot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}, Mesh -> {1, 2}, Boxed -> False, ColorFunction -> "Rainbow", Axes -> False] 

enter image description here

The main problem is that the constructed function should depend on the formal parameters x and y ... should solve it: (

+2
source share

All Articles