add setting transfer function for TriMeshGraphic

This commit is contained in:
wyq 2023-05-13 16:13:37 +08:00
parent cfe03a014b
commit b4b6a7ffd2
6 changed files with 156 additions and 20 deletions

View File

@ -8094,6 +8094,95 @@ public class GraphicFactory {
return meshGraphic;
}
/**
* Create isosurface graphics
*
* @param data 3d data array
* @param x X coordinates
* @param y Y coordinates
* @param z Z coordinates
* @param isoLevel iso level
* @param cData Color data array
* @param ls Legend scheme
* @param nThreads Thread number
* @return Graphics
*/
public static TriMeshGraphic isosurface(final Array data, final Array x, final Array y, final Array z,
final float isoLevel, final Array cData,
TransferFunction transferFunction, int nThreads) {
// TIMER
ArrayList<Thread> threads = new ArrayList<>();
final ArrayList<ArrayList<float[]>> results = new ArrayList<>();
// Thread work distribution
int nz = (int) z.getSize();
int remainder = nz % nThreads;
int segment = nz / nThreads;
// Z axis offset for vertices position calculation
int zAxisOffset = 0;
for (int i = 0; i < nThreads; i++) {
// Distribute remainder among first (remainder) threads
int segmentSize = (remainder-- > 0) ? segment + 1 : segment;
// Padding needs to be added to correctly close the gaps between segments
final int paddedSegmentSize = (i != nThreads - 1) ? segmentSize + 1 : segmentSize;
// Finished callback
final CallbackMC callback = new CallbackMC() {
@Override
public void run() {
results.add(getVertices());
}
};
// Java...
final int finalZAxisOffset = zAxisOffset;
// Start the thread
Thread t = new Thread() {
public void run() {
MarchingCubes.marchingCubes(data, x, y, z, isoLevel, paddedSegmentSize, finalZAxisOffset, callback);
}
};
threads.add(t);
t.start();
// Correct offsets for next iteration
zAxisOffset += segmentSize;
}
// Join the threads
for (int i = 0; i < threads.size(); i++) {
try {
threads.get(i).join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int nVertex = 0;
for (List<float[]> vertices : results) {
nVertex += vertices.size();
}
float[] vertexData = new float[nVertex * 3];
int pos = 0;
for (List<float[]> vertices : results) {
for (int i = 0; i < vertices.size(); i++) {
System.arraycopy(vertices.get(i), 0, vertexData, pos, 3);
pos += 3;
}
}
TriMeshGraphic meshGraphic = new TriMeshGraphic();
meshGraphic.setTriangles(vertexData, cData, x, y, z);
meshGraphic.setTransferFunction(transferFunction);
return meshGraphic;
}
/**
* Create triangle mesh graphic
*

View File

@ -6,6 +6,8 @@ import org.locationtech.jts.triangulate.tri.Tri;
import org.meteoinfo.chart.jogl.JOGLUtil;
import org.meteoinfo.chart.jogl.Transform;
import org.meteoinfo.common.Extent3D;
import org.meteoinfo.geo.legend.LegendManage;
import org.meteoinfo.geometry.colors.TransferFunction;
import org.meteoinfo.geometry.legend.ColorBreak;
import org.meteoinfo.geometry.legend.LegendScheme;
import org.meteoinfo.ndarray.Array;
@ -393,9 +395,9 @@ public class TriMeshGraphic extends GraphicCollection3D {
vertexPosition[idx * 3] = vector3f.x;
vertexPosition[idx * 3 + 1] = vector3f.y;
vertexPosition[idx * 3 + 2] = vector3f.z;
xi = ArrayUtil.searchSorted(xa, vector3f.x);
yi = ArrayUtil.searchSorted(ya, vector3f.y);
zi = ArrayUtil.searchSorted(za, vector3f.z);
xi = ArrayUtil.searchSorted(xa, vector3f.x, true);
yi = ArrayUtil.searchSorted(ya, vector3f.y, true);
zi = ArrayUtil.searchSorted(za, vector3f.z, true);
cIndex.set(zi, yi, xi);
vertexValue[idx] = cData.getFloat(cIndex);
idx += 1;
@ -404,12 +406,57 @@ public class TriMeshGraphic extends GraphicCollection3D {
updateExtent();
}
/**
* Set triangles
* @param vertexData The triangle vertex array
* @param cData Color data array
* @param xa X coordinate array
* @param ya Y coordinate array
* @param za Z coordinate array
*/
public void setVertexValue(Array cData, Array xa, Array ya, Array za) {
int n = getVertexNumber();
this.vertexValue = new float[n];
Index cIndex = cData.getIndex();
int xi, yi, zi;
float x, y, z;
for (int i = 0; i < n; i++) {
x = vertexPosition[i * 3];
y = vertexPosition[i * 3 + 1];
z = vertexPosition[i * 3 + 2];
xi = ArrayUtil.searchSorted(xa, x, true);
yi = ArrayUtil.searchSorted(ya, y, true);
zi = ArrayUtil.searchSorted(za, z, true);
cIndex.set(zi, yi, xi);
vertexValue[i] = cData.getFloat(cIndex);
}
}
@Override
public void setLegendScheme(LegendScheme ls) {
super.setLegendScheme(ls);
updateVertexColor();
}
/**
* Set transfer function
* @param transferFunction Transfer function
*/
public void setTransferFunction(TransferFunction transferFunction) {
if (vertexValue != null) {
vertexColor = new float[getVertexNumber() * 4];
float[] color;
for (int i = 0; i < vertexValue.length; i++) {
color = transferFunction.getColor(vertexValue[i]).getRGBComponents(null);
System.arraycopy(color, 0, vertexColor, i * 4, 4);
}
}
LegendScheme ls = LegendManage.createLegendScheme(transferFunction);
this.legendScheme = ls;
this.setSingleLegend(false);
}
/**
* Update vertex color data
*/

View File

@ -1,32 +1,34 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="milconfig.xml" Type="configurefile">
<Path OpenPath="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volume">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\streamslice"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\radar"/>
<Path OpenPath="D:\Working\MIScript\Jython\mis\LaSW">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\ascii"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\traj"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\chart"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\pie"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\patch"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map\maskout"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\bar"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volume"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\isosurface"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\LaSW"/>
</Path>
<File>
<OpenedFiles>
<OpenedFile File="D:\Working\MIScript\Jython\mis\dataframe\dataframe_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\dataframe\reindex_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volume\volumeplot_perspective_sagittal_specular.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\isosurface\heart_cdata.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\LaSW\typhoon_map_isosurface_ws.py"/>
</OpenedFiles>
<RecentFiles>
<RecentFile File="D:\Working\MIScript\Jython\mis\dataframe\dataframe_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\dataframe\reindex_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volume\volumeplot_perspective_sagittal_specular.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\isosurface\heart_cdata.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\LaSW\typhoon_map_isosurface_ws.py"/>
</RecentFiles>
</File>
<Font>

View File

@ -277,7 +277,7 @@ class Axes3DGL(Axes3D):
"""
Set field of view angles in degrees for perspective projection.
:param fov: (*float*) Field of view angles in degrees.
:param fov: (*float*) Field of view angles in degrees with the range of (0, 180).
"""
if fov <= 0 or fov >= 180:
warnings.warn('Field of view angles should be in the range of (0, 180)')

View File

@ -2254,17 +2254,15 @@ public class ArrayUtil {
break;
}
if (idx >= 0) {
if (idx < 0) {
if (idx == -1) {
idx = 0;
} else {
idx = -idx - 2;
}
if (!left)
idx += 1;
} else {
if (idx == -1)
idx = 0;
else if (idx == -(a.getSize() + 1))
idx = (int)a.getSize();
else {
idx = -idx - 1;
}
}
return idx;