# #005 - From raw data to surface lattice

This is Matlab code that describes a method to regularize raw scattered surface data into a regular lattice. Light scans, such as sonar and LiDAR data, often are segmented into several sections, and each datapoint is irregularly scattered across the surface.

Formalizing several different datasets into a single lattice surface allows for feature visualization and analysis without the compromise of irregularly scattered data that can bias results. The six steps shown here describe a novel original method.

#### Step 1

Load and compile your 3D raw data (fine if datasets spatially overlap), here called `Basin`

, and isolate each spatial dimension into its `X`

, `Y`

, and `Z`

vectors. Extract the maximum and minimum values of each vector using the `nanmax`

and `nanmin`

functions, these six values (two per vector) are the three-dimensional edges of the complete dataset.

```
X=Basin(:,1);Xmin=nanmin(X);Xmax=nanmax(X);
Y=Basin(:,2);Ymin=nanmin(Y);Ymax=nanmax(Y);
Z=Basin(:,3);Zmin=nanmin(Z);Zmax=nanmax(Z);
```

#### Step 2

The following two steps are deceitfully simple: the goal is to create a regular lattice from the known edges. First we make regularly spaced points between the edges of the `X`

and `Y`

dimensions, calling the new regularized vectors `Xi`

and `Yi`

. Then an empty vector filled with ones of length `Yi`

is created as a placeholder for the next step.

The reciprocal of the `step`

number is used as the determinant of length, but I haven’t figured an elegant way to connect the final vector lengths of `Xi`

and `Yi`

with code. The specific numbers shown here (0.5479999999:1 ratio) come from manual trial and error. It has to do with Matlab using index start at `1`

instead of `0`

, but it works!

```
step=24999;
Xi=(Xmin:1/step:Xmax)';
Yi=(Ymin:0.5479999999/step:Ymax)';
string=length(Yi);
newOne=ones(string,1);
```

#### Step 3

This for-loop populates the `newOne`

vector and turns it into a periodic `newX`

vector for every X position in the new lattice. Simultaneously, each iteration adds a new `newY`

value, looping across Y positions until a new X position is required. This creates an XY grid bound within the `nanmax`

and `nanmin`

limits of `X`

and `Y`

.

```
for i=1:string
if i==1
stanzaX=Xi(i,1);
newX=newOne.*stanzaX;
stanzaY=Yi;
newY=stanzaY;
else
stanzaX=Xi(i,1);
longX=newOne.*stanzaX;
newX=cat(1,newX,longX);
stanzaY=Yi;
newY=cat(1,newY,stanzaY);
end
end
```

#### Step 4

Creating the point cloud `ptCloud`

, a placeholder object with all the original `X`

and `Y`

information and a zero dummy vector to be populated by the Z dimension, or the vector `newZ`

.

```
xyzPoints=cat(2,X,Y,zeros(length(Z),1));
ptCloud=pointCloud(xyzPoints);
newZ=zeros(length(newX),1);
```

#### Step 5

In this step everything comes together. The vector `newZ`

gets populated by elevation data from the original `X`

and `Y`

data now in `ptCloud`

using a k-nearest neighbor algorithm, here using the two closest points from the cloud and averaging them to populate the respective `newZ`

point. This is repeated millions of times, so a modulo of every 1000000th iteration prints the `i`

number to check progress. This step takes about 2 hours to complete, depending on how large the datasets are.

```
for i=1:1:length(newX)
b=mod(i,1000000);
if b==0
i
end
point=[newX(i,:),newY(i,:),0];
K=2;
[indices,dists]=findNearestNeighbors(ptCloud,point,K);
pickZ=Z(indices);
pointZ=nanmean(pickZ);
newZ(i,1)=pointZ;
end
```

#### Step 6

Exporting into vectors, and into a final 3D vector, here called `XYZ_Basin`

.

```
XYZ_Basin=cat(3,newX,newY,newZ);
```

This can be exported as a .csv file (or .xyz file) for visualizations in graphical engine software. Here a hacky render is created by stithcing together several stills of the model render while slowly changing the theta angle, while the azimuth remains the same.