The Custom Free Surface 3D Chart Type
In SciChart, Custom Free Surface 3D Charts are provided by the combination of the Free Surface 3D Series and CustomSurfaceDataSeries3D<TX,TY,TZ> underlying DataSeries.
The location of the CustomSurfaceDataSeries3D<TX,TY,TZ> is defined by following properties:
- offsetX – a location of the Custom Free Surface by the
X-Axis
; - offsetY – a location of the Custom Free Surface by the
Y-Axis
; - offsetZ – a location of the Custom Free Surface by the
Z-Axis
;
The shape of its surface is defined by a set of user-defined functions, injected in the Constructor during the instantiation. This approach allows the surface to obtain any possible shape.
Some of the CustomSurfaceDataSeries3D<TX,TY,TZ> Constructor are described below:
- Radial Distance Function – function that determines how distance from the origin to the particular point on the surface differs.
- Azimuthal Angle Function – function that determines the azimuthal angle between the particular point and the unit vector of the X-Axis, projected on the XZ plane.
- Polar Angle Function – is a user-defined function that determines inclination (or polar angle) between the particular point and the unit vector of the
Y-Axis
- Zenith.
Note
The U
and V
coordinates in intervals [uMin...uMax]
and [vMin...vMax]
respectively are passed as the arguments to each of the three functions above.
- X Function - function that determines the position of the particular point on the surface by the
X-Axis
. - Y Function - function that determines the position of the particular point on the surface by the
Y-Axis
. - Z Function - function that determines the position of the particular point on the surface by the
Z-Axis
.
Note
The Radial Distance
, Radial Distance
and Azimuthal Angle
are passed as the arguments to each of the three functions above.
More information about the radial distance, azimuthal and polar angle can be found here: Spherical coordinate system.
Note
Examples for the Custom Free Surface 3D can be found in the SciChart Android Examples Suite as well as on GitHub:
Let's see some examples of declaring some 3D Free Surfaces:
Create a Custom Free Surface 3D Chart
To create a Custom Free Surface 3D Chart like the above - use the following code:
final CustomSurfaceDataSeries3D.UVFunc radialDistanceFunc = (u, v) -> 5d + Math.sin(5 * (u + v));
final CustomSurfaceDataSeries3D.UVFunc azimuthalAngleFunc = (u, v) -> u;
final CustomSurfaceDataSeries3D.UVFunc polarAngleFunc = (u, v) -> v;
final CustomSurfaceDataSeries3D.ValueFunc<Double> xFunc = (r, theta, phi) -> r * Math.sin(theta) * Math.cos(phi);
final CustomSurfaceDataSeries3D.ValueFunc<Double> yFunc = (r, theta, phi) -> r * Math.cos(theta);
final CustomSurfaceDataSeries3D.ValueFunc<Double> zFunc = (r, theta, phi) -> r * Math.sin(theta) * Math.sin(phi);
final CustomSurfaceDataSeries3D<Double, Double, Double> ds = new CustomSurfaceDataSeries3D<>(Double.class, Double.class, Double.class,
30, 30,
radialDistanceFunc, azimuthalAngleFunc, polarAngleFunc,
xFunc, yFunc, zFunc,
0d, Math.PI * 2, 0, Math.PI
);
int[] colors = new int[]{0xFF1D2C6B, Blue, Cyan, GreenYellow, Yellow, Red, DarkRed};
float[] stops = new float[]{0, .1f, .3f, .5f, .7f, .9f, 1};
final GradientColorPalette palette = new GradientColorPalette(colors, stops);
final FreeSurfaceRenderableSeries3D rs = new FreeSurfaceRenderableSeries3D();
rs.setDataSeries(ds);
rs.setDrawMeshAs(DrawMeshAs.SolidWireframe);
rs.setStroke(0x77228B22);
rs.setContourInterval(0.1f);
rs.setContourStroke(0x77228B22);
rs.setStrokeThickness(convertValueToDp(2f));
rs.setLightingFactor(0.8f);
rs.setMeshColorPalette(palette);
rs.setPaletteMinMaxMode(FreeSurfacePaletteMinMaxMode.Relative);
rs.setPaletteMinimum(new Vector3(0f, 5f, 0f));
rs.setPaletteMaximum(new Vector3(0f, 7f, 0f));
Note
See other constrained and unconstrained Free Surface Series types in the corresponding articles.
Create a Simple Sphere
Let's create a simple Sphere with a Radius = 10
.
See the user-defined functions which is used in the CustomSurfaceDataSeries3D<TX,TY,TZ> in the code below:
final CustomSurfaceDataSeries3D.UVFunc radialDistanceFunc = (u, v) -> 10;
final CustomSurfaceDataSeries3D.UVFunc azimuthalAngleFunc = (u, v) -> u;
final CustomSurfaceDataSeries3D.UVFunc polarAngleFunc = (u, v) -> v;
final CustomSurfaceDataSeries3D.ValueFunc<Double> xFunc = (r, theta, phi) -> r * Math.sin(theta) * Math.cos(phi);
final CustomSurfaceDataSeries3D.ValueFunc<Double> yFunc = (r, theta, phi) -> r * Math.cos(theta);
final CustomSurfaceDataSeries3D.ValueFunc<Double> zFunc = (r, theta, phi) -> r * Math.sin(theta) * Math.sin(phi);
final CustomSurfaceDataSeries3D<Double, Double, Double> ds = new CustomSurfaceDataSeries3D<>(Double.class, Double.class, Double.class,
30, 30,
radialDistanceFunc, azimuthalAngleFunc, polarAngleFunc,
xFunc, yFunc, zFunc,
0d, Math.PI * 2, 0, Math.PI
);
Create a Simple Cylinder
Let's create a simple Cylinder with a Radius = 10
and Height = 40
. See the code below:
final CustomSurfaceDataSeries3D.UVFunc radialDistanceFunc = (u, v) -> 0.0;
final CustomSurfaceDataSeries3D.UVFunc azimuthalAngleFunc = (u, v) -> u;
final CustomSurfaceDataSeries3D.UVFunc polarAngleFunc = (u, v) -> v;
final CustomSurfaceDataSeries3D.ValueFunc<Double> xFunc = (r, theta, phi) -> 10 * Math.sin(Math.PI / 2) * Math.cos(phi);
final CustomSurfaceDataSeries3D.ValueFunc<Double> yFunc = (r, theta, phi) -> 40 * Math.cos(theta);
final CustomSurfaceDataSeries3D.ValueFunc<Double> zFunc = (r, theta, phi) -> 10 * Math.sin(Math.PI / 2) * Math.sin(phi);
final CustomSurfaceDataSeries3D<Double, Double, Double> ds = new CustomSurfaceDataSeries3D<>(Double.class, Double.class, Double.class,
30, 30,
radialDistanceFunc, azimuthalAngleFunc, polarAngleFunc,
xFunc, yFunc, zFunc,
0d, Math.PI * 2, 0, Math.PI
);