How to plot customly-shaped set of 3D points each connected to its neighbors?

You can restrict your PlotRegion in Plot3D

Plot3D[1,{x,0,5},{y,-1,4},RegionFunction->(Sin[#1]<#2<Cos[#1]+3&)]

enter image description here

For more complicated Regions you should use RegionPlot3D. Here is the restriction for all 3 dimensions (which creates a beautiful figure if you ask me):

RegionPlot3D[(Sin[x]<y<Cos[x]+3)&&(Sin[y]<z<Cos[y]+3)&&(Sin[z]<x<Cos[z]+3),{x,-1,4},{y,-1,4},{z,-1,4},MaxRecursion->10,PlotPoints->100]

enter image description here


If the points form a deformed rectangular grid, then you can use the method below; otherwise, the methods of the following question should work:

DelaunayMesh in a specified closed region - creating a concave hull from a set of points

For a tensor grid of points:

pts = N@Table[{x, y, Cos[x] Sin[y]},  (* varying height *)
    {x, 0, 5, 5/60},
    {y, Sin[x], Cos[x] + 3, (Cos[x] + 3 - Sin[x])/60}];

With[{p = Flatten[pts, 1]},
 Graphics3D[
  GraphicsComplex[
   p,
   {EdgeForm[], ColorData[97][2],
    Polygon[
     Flatten[#][[{1, 2, 4, 3}]] & /@ Flatten[Partition[
        Partition[Range@Length@p, Length@First@pts],
        {2, 2}, {1, 1}],
       1]
     ]}
   ]]]

Mathematica graphics

It works even better if the height is a constant 1.


ListPlot3D accepts RegionFunction, so let's exploit this fact. The idea is to create a region.

data = Flatten[#, 1] &@
  Table[{x, y, 1}, {x, 0, 5, 5/60}, {y, Sin[x], 
    Cos[x] + 3, (Cos[x] + 3 - Sin[x])/60}]

data2D = data[[All, 1 ;; 2]]

range = {{0, 5}, {-1, 4}}

First, Binarize the region

reg = Binarize@
  ListPlot[data2D, Axes -> False, AspectRatio -> 1, 
   PlotStyle -> PointSize -> Large]

so that one can use the functions of bobthechemist and rhermans:

binaryImageToRegion[bimg_] := 
 With[{idata = ImageData[bimg], xmax = First@ImageDimensions[bimg], 
   ymax = Last@ImageDimensions[bimg]}, 
  BoundaryDiscretizeGraphics@
   First@RegionPlot[
     idata[[IntegerPart@(ymax - y), IntegerPart@x]] == 1, {x, 1, 
      xmax}, {y, 1, ymax}]]

reg1 = binaryImageToRegion[ColorNegate@reg]

enter image description here

{100, 100} \[Element] reg1
{200, 200} \[Element] reg1

False

True

and

imgregion[im_] := 
 Polygon[Part[#, Last@FindShortestTour[#]] &@
   PixelValuePositions[
    MorphologicalPerimeter[
     Erosion[FillingTransform@ColorNegate@Binarize[im, 0.91], 2], 
     CornerNeighbors -> False], 1]]

reg2 = BoundaryDiscretizeRegion@imgregion[reg];

plot = RegionPlot@reg2

enter image description here

{100, 100} \[Element] reg2
{200, 200} \[Element] reg2

False

True

I'll use reg1 here; exactly the same results were obtained with reg2.

We need to translate the coordinates in data, which are in the range, so that they correspond to those in reg1. We need to take dimensions of the RegionPlot of reg1, without the Frame:

id = ImageDimensions @ RegionPlot[#, Frame -> None] &@reg1

{360, 360}

I calculated it with pen and paper, but it's easy (the transformation is linear) to do it automatically. With the derived RegionFunction:

ListPlot3D[data, 
 RegionFunction -> 
  Function[{x, y, z}, {72 x, (y + 1) 72} \[Element] reg1]]

enter image description here