All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.mihosoft.vrl.v3d.thumbnail.ThumbnailImage Maven / Gradle / Ivy

package eu.mihosoft.vrl.v3d.thumbnail;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;

import eu.mihosoft.vrl.v3d.Bounds;
import eu.mihosoft.vrl.v3d.CSG;
import eu.mihosoft.vrl.v3d.Vector3d;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SnapshotParameters;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.MeshView;
import javafx.scene.transform.Transform;
import javafx.scene.PerspectiveCamera;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.transform.Affine;
import javafx.scene.transform.Transform;
import javafx.scene.transform.Rotate;
import javafx.geometry.Rectangle2D;

public class ThumbnailImage {
	private static CullFace cullFaceValue = CullFace.BACK;

	public static Bounds getSellectedBounds(List incoming) {
		Vector3d min = null;
		Vector3d max = null;
		for (CSG c : incoming) {
			if (c.isHide())
				continue;
			if (c.isInGroup())
				continue;
			Vector3d min2 = c.getBounds().getMin().clone();
			Vector3d max2 = c.getBounds().getMax().clone();
			if (min == null)
				min = min2;
			if (max == null)
				max = max2;
			if (min2.x < min.x)
				min.x = min2.x;
			if (min2.y < min.y)
				min.y = min2.y;
			if (min2.z < min.z)
				min.z = min2.z;
			if (max.x < max2.x)
				max.x = max2.x;
			if (max.y < max2.y)
				max.y = max2.y;
			if (max.z < max2.z)
				max.z = max2.z;
		}
		if (max == null)
			max = new Vector3d(0, 0, 0);
		if (min == null)
			min = new Vector3d(0, 0, 0);
		return new Bounds(min, max);
	}

	public static WritableImage get(List c) {
		ArrayList csgList = new ArrayList();
		for (CSG cs : c) {
			if (cs.getManipulator() != null) {
				csgList.add(cs.transformed(TransformConverter.fromAffine(cs.getManipulator())).syncProperties(cs));
			} else
				csgList.add(cs);
		}
		// Create a group to hold all the meshes
		Group root = new Group();

		// Add all meshes to the group
		Bounds b = getSellectedBounds(csgList);

		double yOffset = (b.getMax().y - b.getMin().y) / 2;
		double xOffset = (b.getMax().x - b.getMin().x) / 2;
		double zCenter = (b.getMax().z - b.getMin().z) / 2;
		for (CSG csg : csgList) {
			if (csg.isHide())
				continue;
			if (csg.isInGroup())
				continue;
			MeshView meshView = csg.movez(-zCenter).getMesh();
			if (csg.isHole()) {
				PhongMaterial material = new PhongMaterial();
				material.setDiffuseColor(new Color(0.25, 0.25, 0.25, 0.75));
				material.setSpecularColor(javafx.scene.paint.Color.WHITE);
				meshView.setMaterial(material);
				meshView.setOpacity(0.25);
			}
			meshView.setCullFace(getCullFaceValue());
			root.getChildren().add(meshView);
		}

		// Calculate the bounds of all CSGs combined
		double totalz = b.getMax().z - b.getMin().z;
		double totaly = b.getMax().y - b.getMin().y;
		double totalx = b.getMax().x - b.getMin().x;

		// Create a perspective camera
		PerspectiveCamera camera = new PerspectiveCamera(true);

		// Calculate camera position to fit all objects in view
		double maxDimension = Math.max(totalx, Math.max(totaly, totalz));
		double cameraDistance = (maxDimension / Math.tan(Math.toRadians(camera.getFieldOfView() / 2))) * 0.8;

//		TransformNR camoffset = new TransformNR(xOffset, yOffset, 0);
//		TransformNR camDist = new TransformNR(0, 0, -cameraDistance);
//		TransformNR rot = new TransformNR(new RotationNR(-150, 45, 0));
//		
//		Affine af = TransformFactory.nrToAffine(camoffset.times(rot.times(camDist)));
		Affine camDist = new Affine();
		camDist.setTz(-cameraDistance);
		Rotate rot1 = new Rotate(45, Rotate.Z_AXIS);
		Rotate rot2 = new Rotate(-150, Rotate.Y_AXIS);
		Affine camoffset = new Affine();
		camoffset.setTx(xOffset);
		camoffset.setTy(yOffset);
		camera.getTransforms().add(camoffset);
		camera.getTransforms().add(rot2);
		camera.getTransforms().add(rot1);
		camera.getTransforms().add(camDist);
		//

		// Position the camera
//	    camera.setTranslateX();
//	    camera.setTranslateY();
//		camera.setTranslateZ();
//		   // Apply rotations to the root group instead of the camera
//	    root.getTransforms().addAll(
//	            new Rotate(-5, Rotate.Y_AXIS),
//	            new Rotate(-45, Rotate.X_AXIS)
//	    );
		// Create a scene with the group and camera
		int i = 1000;
		Scene scene = new Scene(root, i, i, true, SceneAntialiasing.BALANCED);
		scene.setFill(Color.TRANSPARENT);
		scene.setCamera(camera);

		// Set up snapshot parameters
		SnapshotParameters params = new SnapshotParameters();
		params.setFill(Color.TRANSPARENT);
		params.setCamera(camera);
		params.setDepthBuffer(true);
		params.setTransform(Transform.scale(1, 1));
		// Set the near and far clip
		camera.setNearClip(0.1); // Set the near clip plane
		camera.setFarClip(9000.0); // Set the far clip plane

		// Create the WritableImage first
		WritableImage snapshot = new WritableImage(i, i);

		root.snapshot(params, snapshot);

		return snapshot;
	}

	public static Thread writeImage(CSG incoming, File toPNG) {
		ArrayList bits = new ArrayList();
		bits.add(incoming);
		return writeImage(bits, toPNG);
	}

	public static Thread writeImage(ArrayList incoming, File toPNG) {
		Thread t = new Thread(new Runnable() {
			WritableImage img = null;

			@Override
			public void run() {
				File image = toPNG;
				javafx.application.Platform.runLater(() -> img = ThumbnailImage.get(incoming));
				while (img == null)
					try {
						Thread.sleep(16);
						// com.neuronrobotics.sdk.common.Log.error("Waiting for image to write");
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						break;
					}
				BufferedImage bufferedImage = SwingFXUtils.fromFXImage(img, null);

				try {
					ImageIO.write(bufferedImage, "png", image);
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
		});
		t.setUncaughtExceptionHandler((thread, throwable) -> {
			throwable.printStackTrace();
			thread.interrupt();
		});
		t.start();
		return t;
	}

	public static CullFace getCullFaceValue() {
		return cullFaceValue;
	}

	public static void setCullFaceValue(CullFace cullFaceValue) {
		ThumbnailImage.cullFaceValue = cullFaceValue;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy