<commit_before>/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package org.opensim.threejs;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import org.json.simple.JSONArray;
import org.opensim.modeling.DecorativeArrow;
import org.opensim.modeling.DecorativeBrick;
import org.opensim.modeling.DecorativeCircle;
import org.opensim.modeling.DecorativeCone;
import org.opensim.modeling.DecorativeCylinder;
import org.opensim.modeling.DecorativeEllipsoid;
import org.opensim.modeling.DecorativeFrame;
import org.opensim.modeling.DecorativeGeometry;
import org.opensim.modeling.DecorativeGeometryImplementation;
import org.opensim.modeling.DecorativeLine;
import org.opensim.modeling.DecorativeMesh;
import org.opensim.modeling.DecorativeMeshFile;
import org.opensim.modeling.DecorativePoint;
import org.opensim.modeling.DecorativeSphere;
import org.opensim.modeling.DecorativeText;
import org.opensim.modeling.DecorativeTorus;
import org.opensim.modeling.PolygonalMesh;
import org.opensim.modeling.Vec3;
import org.opensim.view.pub.GeometryFileLocator;


/**
 *
 * @author Ayman
 */ 
public class DecorativeGeometryImplementationJS extends DecorativeGeometryImplementation {
    private JSONArray jsonArr;
    private UUID geomID;
    private double visualizerScaleFactor = 100;
    public DecorativeGeometryImplementationJS(JSONArray jsonArr, double scale) {
        this.jsonArr = jsonArr;
        this.visualizerScaleFactor = scale;
    }
    
    @Override
    public void implementConeGeometry(DecorativeCone arg0) {
        Map dg_json = new LinkedHashMap();
        dg_json.put("uuid", geomID.toString());
        dg_json.put("type", "CylinderGeometry");
	dg_json.put("radiusTop", 0.);
	dg_json.put("radiusBottom", arg0.getBaseRadius()*visualizerScaleFactor);
	dg_json.put("widthSegments", 32);
	dg_json.put("heightSegments", 1);
        jsonArr.add(dg_json);     
    }

    @Override
    public void implementArrowGeometry(DecorativeArrow arg0) {
        //super.implementArrowGeometry(arg0); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void implementTorusGeometry(DecorativeTorus arg0) {
        /*
            "type": "TorusGeometry",
            "radius": 100,
            "tube": 40,
            "radialSegments": 8,
            "tubularSegments": 6,
            "arc": 6.283185307179586 */
        Map dg_json = new LinkedHashMap();
        dg_json.put("uuid", geomID.toString());
        dg_json.put("type", "TorusGeometry");
	dg_json.put("radius", arg0.getTorusRadius()*visualizerScaleFactor);
	dg_json.put("tube", arg0.getTubeRadius()*visualizerScaleFactor);
	dg_json.put("radialSegments", 32);
	dg_json.put("tubularSegments", 24);
        jsonArr.add(dg_json);        
     }

    @Override
    public void implementMeshFileGeometry(DecorativeMeshFile arg0) {
        //super.implementMeshFileGeometry(arg0); //To change body of generated methods, choose Tools | Templates.
        String meshFile = arg0.getMeshFile();
        String fullFileName = GeometryFileLocator.getInstance().getFullname("",meshFile, false);
        System.out.print("Processing file"+fullFileName);
        if (fullFileName==null) return;
        System.out.println("...Found");
        String filenameLower = fullFileName.toLowerCase();
        if (filenameLower.endsWith(".vtp") || filenameLower.endsWith(".stl") || filenameLower.endsWith(".obj")){
            // Create json for vtp
            Map dg_json = new LinkedHashMap();
            dg_json.put("uuid", geomID.toString());
            dg_json.put("type", "BufferGeometry");
            Map attributes_json = new LinkedHashMap();
            // Make position json entry
            /*
                    "position": {
                        "itemSize": 3,
                        "type": "Float32Array",
                        "array": [0,0,0,100,0,0,100,100,0]
                    }
            */
            Map pos_json = new LinkedHashMap();
            pos_json.put("itemSize", 3);
            pos_json.put("type", "Float32Array");
            
            // Build JSONArrays for attributes, normal
            JSONArray pos_array = new JSONArray();
            Map data_json = new LinkedHashMap();
            PolygonalMesh mesh = new PolygonalMesh();
            mesh.loadFile(fullFileName);
            int nv = mesh.getNumVertices();
            for (int v=0; v < nv; v++){
                Vec3 vec3 = mesh.getVertexPosition(v);
                for (int coord=0; coord <3; coord++){
                    pos_array.add(vec3.get(coord)*visualizerScaleFactor);
                 }
            }
            pos_json.put("array", pos_array);
            attributes_json.put("position", pos_json);
            // Now the index to pass connectivity
            /*
            "index": {
                        "itemSize": 3,
                        "type" : "Uint16Array",
                        "array": [3,0,1,3,2,0]
                 }
            */
            Map index_json = new LinkedHashMap();
            JSONArray index_array = new JSONArray();
            int nf = mesh.getNumFaces();
            for (int f=0; f < nf; f++){
                int numVerts = mesh.getNumVerticesForFace(f);
                for (int vi=0; vi <numVerts-2; vi++){
                    index_array.add(mesh.getFaceVertex(f, 0));
                    index_array.add(mesh.getFaceVertex(f, vi+1));
                    index_array.add(mesh.getFaceVertex(f, vi+2));
                 }
            }<commit_msg>Compute vertex normals for Mesh<commit_after>/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package org.opensim.threejs;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import org.json.simple.JSONArray;
import org.opensim.modeling.DecorativeArrow;
import org.opensim.modeling.DecorativeBrick;
import org.opensim.modeling.DecorativeCircle;
import org.opensim.modeling.DecorativeCone;
import org.opensim.modeling.DecorativeCylinder;
import org.opensim.modeling.DecorativeEllipsoid;
import org.opensim.modeling.DecorativeFrame;
import org.opensim.modeling.DecorativeGeometryImplementation;
import org.opensim.modeling.DecorativeLine;
import org.opensim.modeling.DecorativeMesh;
import org.opensim.modeling.DecorativeMeshFile;
import org.opensim.modeling.DecorativePoint;
import org.opensim.modeling.DecorativeSphere;
import org.opensim.modeling.DecorativeText;
import org.opensim.modeling.DecorativeTorus;
import org.opensim.modeling.PolygonalMesh;
import org.opensim.modeling.Vec3;
import org.opensim.view.pub.GeometryFileLocator;


/**
 *
 * @author Ayman
 */ 
public class DecorativeGeometryImplementationJS extends DecorativeGeometryImplementation {
    private JSONArray jsonArr;
    private UUID geomID;
    private double visualizerScaleFactor = 100;
    public DecorativeGeometryImplementationJS(JSONArray jsonArr, double scale) {
        this.jsonArr = jsonArr;
        this.visualizerScaleFactor = scale;
    }
    
    @Override
    public void implementConeGeometry(DecorativeCone arg0) {
        Map dg_json = new LinkedHashMap();
        dg_json.put("uuid", geomID.toString());
        dg_json.put("type", "CylinderGeometry");
	dg_json.put("radiusTop", 0.);
	dg_json.put("radiusBottom", arg0.getBaseRadius()*visualizerScaleFactor);
	dg_json.put("widthSegments", 32);
	dg_json.put("heightSegments", 1);
        jsonArr.add(dg_json);     
    }

    @Override
    public void implementArrowGeometry(DecorativeArrow arg0) {
        //super.implementArrowGeometry(arg0); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void implementTorusGeometry(DecorativeTorus arg0) {
        /*
            "type": "TorusGeometry",
            "radius": 100,
            "tube": 40,
            "radialSegments": 8,
            "tubularSegments": 6,
            "arc": 6.283185307179586 */
        Map dg_json = new LinkedHashMap();
        dg_json.put("uuid", geomID.toString());
        dg_json.put("type", "TorusGeometry");
	dg_json.put("radius", arg0.getTorusRadius()*visualizerScaleFactor);
	dg_json.put("tube", arg0.getTubeRadius()*visualizerScaleFactor);
	dg_json.put("radialSegments", 32);
	dg_json.put("tubularSegments", 24);
        jsonArr.add(dg_json);        
     }

    @Override
    public void implementMeshFileGeometry(DecorativeMeshFile arg0) {
        //super.implementMeshFileGeometry(arg0); //To change body of generated methods, choose Tools | Templates.
        String meshFile = arg0.getMeshFile();
        String fullFileName = GeometryFileLocator.getInstance().getFullname("",meshFile, false);
        System.out.print("Processing file"+fullFileName);
        if (fullFileName==null) return;
        System.out.println("...Found");
        String filenameLower = fullFileName.toLowerCase();
        if (filenameLower.endsWith(".vtp") || filenameLower.endsWith(".stl") || filenameLower.endsWith(".obj")){
            // Create json for vtp
            Map dg_json = new LinkedHashMap();
            dg_json.put("uuid", geomID.toString());
            dg_json.put("type", "BufferGeometry");
            Map attributes_json = new LinkedHashMap();
            // Make position json entry
            /*
                    "position": {
                        "itemSize": 3,
                        "type": "Float32Array",
                        "array": [0,0,0,100,0,0,100,100,0]
                    }
            */
            Map pos_json = new LinkedHashMap();
            pos_json.put("itemSize", 3);
            pos_json.put("type", "Float32Array");
            Map normals_json = new LinkedHashMap();
            normals_json.put("itemSize", 3);
            normals_json.put("type", "Float32Array");
            
            PolygonalMesh mesh = new PolygonalMesh();
            mesh.loadFile(fullFileName);
            int nv = mesh.getNumVertices();
            
            int nf = mesh.getNumFaces();
            Vec3[] normals = new Vec3[nv];
            for (int f=0; f < nf; f++){
                 // get first three face indices, form normal from cross product
                //System.out.println("f="+f);
                Vec3[] verts = new Vec3[3];
                for (int i=0; i<3; i++){
                    verts[i] = mesh.getVertexPosition(mesh.getFaceVertex(f, i));
                }
                Vec3 side1 = new Vec3();
                Vec3 side2 = new Vec3();
                for (int i=0; i<3; i++){
                    side1.set(i, verts[1].get(i) - verts[0].get(i));
                    side2.set(i, verts[2].get(i) - verts[0].get(i));
                }
                Vec3 cross = new Vec3(side1.get(1)*side2.get(2)-side1.get(2)*side2.get(1),
                                    side1.get(0)*side2.get(2)-side1.get(2)*side2.get(0),
                                    side1.get(0)*side2.get(1)-side1.get(1)*side2.get(0));
                double norm = Math.sqrt(cross.get(0)*cross.get(0)+
                        cross.get(1)*cross.get(1)+cross.get(2)*cross.get(2));
                for (int i=0; i<3; i++) cross.set(i, cross.get(i)/norm);
                int nvf = mesh.getNumVerticesForFace(f);
                for (int i=0; i<nvf; i++){
                    int vindex = mesh.getFaceVertex(f, i);
                    //System.out.print("f-v:"+vindex);
                    normals[vindex]= cross;
                }
                //System.out.println("");   
            }
            // Build JSONArrays for attributes, normal
            JSONArray pos_array = new JSONArray();
            JSONArray normals_array = new JSONArray();
            Map data_json = new LinkedHashMap();
            for (int v=0; v < nv; v++){
                Vec3 vec3 = mesh.getVertexPosition(v);
                for (int coord=0; coord <3; coord++){
                    pos_array.add(vec3.get(coord)*visualizerScaleFactor);
                 }
                //System.out.println("v="+v+" normal =:"+normals[v].toString());
                if (normals[v]!=null){
                    normals_array.add(normals[v].get(0));
                    normals_array.add(normals[v].get(1));
                    normals_array.add(normals[v].get(2));
                }
                else {
                    normals_array.add(0.0);
                    normals_array.add(0.0);
                    normals_array.add(0.0);
                }
            }
            pos_json.put("array", pos_array);
            normals_json.put("array", normals_array);
            attributes_json.put("position", pos_json);
            attributes_json.put("normal", normals_json);
            // Now the index to pass connectivity
            /*
            "index": {
                        "itemSize": 3,
                        "type" : "Uint16Array",
                        "array": [3,0,1,3,2,0]
                 }
            */
            Map index_json = new LinkedHashMap();
            JSONArray index_array = new JSONArray();
            for (int f=0; f < nf; f++){
                int numVerts = mesh.getNumVerticesForFace(f);
                for (int vi=0; vi <numVerts-2; vi++){
                    index_array.add(mesh.getFaceVertex(f, 0));
                    index_array.add(mesh.getFaceVertex(f, vi+1));
                    index_array.add(mesh.getFaceVertex(f, vi+2));
                 }
            }
{'fraction_non_alphanumeric': 0.12101677532781481, 'fraction_numerical': 0.0178008937074207, 'mean_word_length': 2.178579743888242, 'pattern_counts': {'":': 26, '<': 16, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '536875', 'n_tokens_mistral': 4175, 'n_tokens_neox': 3988, 'n_words': 773}