<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.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.openide.util.Exceptions;
import org.opensim.modeling.ArrayDecorativeGeometry;
import org.opensim.modeling.BodyList;
import org.opensim.modeling.Body;
import org.opensim.modeling.BodyIterator;
import org.opensim.modeling.Component;
import org.opensim.modeling.ComponentIterator;
import org.opensim.modeling.ComponentsList;
import org.opensim.modeling.DecorativeGeometry;
import org.opensim.modeling.GeometryPath;
import org.opensim.modeling.Model;
import org.opensim.modeling.ModelDisplayHints;
import org.opensim.modeling.MuscleList;
import org.opensim.modeling.OpenSimObject;
import org.opensim.modeling.PathPoint;
import org.opensim.modeling.PathPointSet;
import org.opensim.modeling.PhysicalFrame;
import org.opensim.modeling.State;
import org.opensim.modeling.Transform;
import org.opensim.modeling.Vec3;

/**
 *
 * @author Ayman
 */
public class VisualizationJson {
    private State state;
    private final JSONObject topJson;
    private final HashMap<Integer, PhysicalFrame> mapBodyIndicesToFrames = new HashMap<Integer, PhysicalFrame>();
    private final HashMap<Integer, JSONObject> mapBodyIndicesToJson = new HashMap<Integer, JSONObject>();
    private final static double visScaleFactor = 1000.0;
    private final HashMap<String, UUID> mapDecorativeGeometryToUUID = new HashMap<String, UUID>();
    private final HashMap<UUID, Component> mapUUIDToComponent = new HashMap<UUID, Component>();
    private final HashMap<OpenSimObject, ArrayList<UUID>> mapComponentToUUID = 
            new HashMap<OpenSimObject, ArrayList<UUID>>();
    private final HashMap<String, UUID> mapPathMaterialToUUID = new HashMap<String, UUID>();
    private static final String GEOMETRY_SEP = ".";
    private final Vec3 vec3Unit = new Vec3(1.0, 1.0, 1.0);
    private MuscleList muscleList = null;
    private ModelDisplayHints mdh;
    private DecorativeGeometryImplementationJS dgimp = null;
    private static String boneSuffix = "_Bone";
    
    public VisualizationJson(Model model) {
        topJson =  createJsonForModel(model);
    }
    private JSONObject createJsonForModel(Model model) {
        state = model.getWorkingState();
        mdh = model.getDisplayHints();
        ComponentsList mcList = model.getComponentsList();
        muscleList = model.getMuscleList();
        ComponentIterator mcIter = mcList.begin();
        // Load template 
        JSONObject jsonTop = loadTemplateJSON();
        BodyList bodies = model.getBodyList();
        BodyIterator body = bodies.begin();
        mapBodyIndicesToFrames.put(0, model.getGround());
        
        JSONArray json_geometries = (JSONArray) jsonTop.get("geometries");
        JSONArray json_materials = (JSONArray) jsonTop.get("materials");
        JSONObject sceneObject = (JSONObject) jsonTop.get("object");
        JSONArray json_scene_children = (JSONArray) sceneObject.get("children");
        
        JSONObject model_json = new JSONObject();
        json_scene_children.add(model_json);
        // create model node
        model_json.put("uuid", UUID.randomUUID().toString());
        model_json.put("type", "Group");
        model_json.put("opensimtype", "Frame");
        model_json.put("name", model.getGround().getFullPathName());
        model_json.put("model_ground", true);
        //System.out.println(model_json.toJSONString());
        JSONArray bodies_json = new JSONArray();
        model_json.put("children", bodies_json);
        mapBodyIndicesToJson.put(0, model_json);
        while (!body.equals(bodies.end())) {
            int id = body.getMobilizedBodyIndex();
            mapBodyIndicesToFrames.put(id, body.__deref__());
            //System.out.println("id=" + id + " body =" + body.getName());
            JSONObject bodyJson = createBodyJson(body.__deref__());
            mapBodyIndicesToJson.put(id, bodyJson);
            bodies_json.add(bodyJson);
            //System.out.println(bodyJson.toJSONString());
            body.next();
        }
        //createSkeleton(model, jsonTop);
        dgimp = new DecorativeGeometryImplementationJS(json_geometries, json_materials, visScaleFactor);
        while (!mcIter.equals(mcList.end())) {
            Component comp = mcIter.__deref__();
            ArrayDecorativeGeometry adg = new ArrayDecorativeGeometry();
            comp.generateDecorations(true, mdh, model.getWorkingState(), adg);
            if (adg.size() > 0) {
                processDecorativeGeometry(adg, comp, dgimp, json_materials);
            }
            GeometryPath gPath = GeometryPath.safeDownCast(comp);
            boolean isGeometryPath = (gPath!=null);
            if (isGeometryPath)
                createJsonForGeometryPath(gPath, mdh, model.getWorkingState(), json_geometries, json_materials);
            else{
                adg.clear();
                comp.generateDecorations(false, mdh, model.getWorkingState(), adg);
                 if (adg.size() > 0) {
                    processDecorativeGeometry(adg, comp, dgimp, json_materials);
                }
            }
            mcIter.next();
        }
        return jsonTop;
    }

    private void processDecorativeGeometry(ArrayDecorativeGeometry adg, Component comp, 
            DecorativeGeometryImplementationJS dgimp, JSONArray json_materials) {
        DecorativeGeometry dg;
        ArrayList<UUID> vis_uuidList = new ArrayList<UUID>(1);
        for (int idx = 0; idx < adg.size(); idx++) {
            dg = adg.getElt(idx);
            String geomId = comp.getFullPathName();
            if (adg.size()>1)
                geomId = geomId.concat(GEOMETRY_SEP+String.valueOf(dg.getIndexOnBody()));
            UUID uuid = UUID.randomUUID();
            mapDecorativeGeometryToUUID.put(geomId, uuid);
            dgimp.setGeomID(uuid);
            dg.implementGeometry(dgimp);
            JSONObject bodyJson = mapBodyIndicesToJson.get(dg.getBodyId());
            if (bodyJson.get("children")==null)
                bodyJson.put("children", new JSONArray());
            UUID uuid_mesh = addtoFrameJsonObject(dg, geomId, uuid, dgimp.getMat_uuid(), (JSONArray)bodyJson.get("children"));
            vis_uuidList.add(uuid_mesh);
            
            mapUUIDToComponent.put(uuid_mesh, comp);
        }
        mapComponentToUUID.put(comp, vis_uuidList);
        System.out.println("Map component="+comp.getFullPathName()+" to "+vis_uuidList.size());   
 
    }

    private JSONObject loadTemplateJSON() {
        JSONParser parser = new JSONParser();
        JSONObject jsonObject = null;
        String current;
        try {
            current = new java.io.File( "." ).getCanonicalPath();
            System.out.println("Current dir:"+current);
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
        
        try {
            Object obj = parser.parse(new FileReader("visResources/templateScene.json"));
            jsonObject = (JSONObject) obj;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonObject;
    }

    private UUID addtoFrameJsonObject(DecorativeGeometry dg, String geomName, UUID uuid, UUID uuid_mat, JSONArray mobody_objects) {
        Map<String, Object> obj_json = new LinkedHashMap<String, Object>();
        UUID mesh_uuid = UUID.randomUUID();
        obj_json.put("uuid", mesh_uuid.toString());<commit_msg>Update location of templateScene.json to live with visualizer.<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.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.openide.util.Exceptions;
import org.opensim.modeling.ArrayDecorativeGeometry;
import org.opensim.modeling.BodyList;
import org.opensim.modeling.Body;
import org.opensim.modeling.BodyIterator;
import org.opensim.modeling.Component;
import org.opensim.modeling.ComponentIterator;
import org.opensim.modeling.ComponentsList;
import org.opensim.modeling.DecorativeGeometry;
import org.opensim.modeling.GeometryPath;
import org.opensim.modeling.Model;
import org.opensim.modeling.ModelDisplayHints;
import org.opensim.modeling.MuscleList;
import org.opensim.modeling.OpenSimObject;
import org.opensim.modeling.PathPoint;
import org.opensim.modeling.PathPointSet;
import org.opensim.modeling.PhysicalFrame;
import org.opensim.modeling.State;
import org.opensim.modeling.Transform;
import org.opensim.modeling.Vec3;

/**
 *
 * @author Ayman
 */
public class VisualizationJson {
    private State state;
    private final JSONObject topJson;
    private final HashMap<Integer, PhysicalFrame> mapBodyIndicesToFrames = new HashMap<Integer, PhysicalFrame>();
    private final HashMap<Integer, JSONObject> mapBodyIndicesToJson = new HashMap<Integer, JSONObject>();
    private final static double visScaleFactor = 1000.0;
    private final HashMap<String, UUID> mapDecorativeGeometryToUUID = new HashMap<String, UUID>();
    private final HashMap<UUID, Component> mapUUIDToComponent = new HashMap<UUID, Component>();
    private final HashMap<OpenSimObject, ArrayList<UUID>> mapComponentToUUID = 
            new HashMap<OpenSimObject, ArrayList<UUID>>();
    private final HashMap<String, UUID> mapPathMaterialToUUID = new HashMap<String, UUID>();
    private static final String GEOMETRY_SEP = ".";
    private final Vec3 vec3Unit = new Vec3(1.0, 1.0, 1.0);
    private MuscleList muscleList = null;
    private ModelDisplayHints mdh;
    private DecorativeGeometryImplementationJS dgimp = null;
    private static String boneSuffix = "_Bone";
    
    public VisualizationJson(Model model) {
        topJson =  createJsonForModel(model);
    }
    private JSONObject createJsonForModel(Model model) {
        state = model.getWorkingState();
        mdh = model.getDisplayHints();
        ComponentsList mcList = model.getComponentsList();
        muscleList = model.getMuscleList();
        ComponentIterator mcIter = mcList.begin();
        // Load template 
        JSONObject jsonTop = loadTemplateJSON();
        BodyList bodies = model.getBodyList();
        BodyIterator body = bodies.begin();
        mapBodyIndicesToFrames.put(0, model.getGround());
        
        JSONArray json_geometries = (JSONArray) jsonTop.get("geometries");
        JSONArray json_materials = (JSONArray) jsonTop.get("materials");
        JSONObject sceneObject = (JSONObject) jsonTop.get("object");
        JSONArray json_scene_children = (JSONArray) sceneObject.get("children");
        
        JSONObject model_json = new JSONObject();
        json_scene_children.add(model_json);
        // create model node
        model_json.put("uuid", UUID.randomUUID().toString());
        model_json.put("type", "Group");
        model_json.put("opensimtype", "Frame");
        model_json.put("name", model.getGround().getFullPathName());
        model_json.put("model_ground", true);
        //System.out.println(model_json.toJSONString());
        JSONArray bodies_json = new JSONArray();
        model_json.put("children", bodies_json);
        mapBodyIndicesToJson.put(0, model_json);
        while (!body.equals(bodies.end())) {
            int id = body.getMobilizedBodyIndex();
            mapBodyIndicesToFrames.put(id, body.__deref__());
            //System.out.println("id=" + id + " body =" + body.getName());
            JSONObject bodyJson = createBodyJson(body.__deref__());
            mapBodyIndicesToJson.put(id, bodyJson);
            bodies_json.add(bodyJson);
            //System.out.println(bodyJson.toJSONString());
            body.next();
        }
        //createSkeleton(model, jsonTop);
        dgimp = new DecorativeGeometryImplementationJS(json_geometries, json_materials, visScaleFactor);
        while (!mcIter.equals(mcList.end())) {
            Component comp = mcIter.__deref__();
            ArrayDecorativeGeometry adg = new ArrayDecorativeGeometry();
            comp.generateDecorations(true, mdh, model.getWorkingState(), adg);
            if (adg.size() > 0) {
                processDecorativeGeometry(adg, comp, dgimp, json_materials);
            }
            GeometryPath gPath = GeometryPath.safeDownCast(comp);
            boolean isGeometryPath = (gPath!=null);
            if (isGeometryPath)
                createJsonForGeometryPath(gPath, mdh, model.getWorkingState(), json_geometries, json_materials);
            else{
                adg.clear();
                comp.generateDecorations(false, mdh, model.getWorkingState(), adg);
                 if (adg.size() > 0) {
                    processDecorativeGeometry(adg, comp, dgimp, json_materials);
                }
            }
            mcIter.next();
        }
        return jsonTop;
    }

    private void processDecorativeGeometry(ArrayDecorativeGeometry adg, Component comp, 
            DecorativeGeometryImplementationJS dgimp, JSONArray json_materials) {
        DecorativeGeometry dg;
        ArrayList<UUID> vis_uuidList = new ArrayList<UUID>(1);
        for (int idx = 0; idx < adg.size(); idx++) {
            dg = adg.getElt(idx);
            String geomId = comp.getFullPathName();
            if (adg.size()>1)
                geomId = geomId.concat(GEOMETRY_SEP+String.valueOf(dg.getIndexOnBody()));
            UUID uuid = UUID.randomUUID();
            mapDecorativeGeometryToUUID.put(geomId, uuid);
            dgimp.setGeomID(uuid);
            dg.implementGeometry(dgimp);
            JSONObject bodyJson = mapBodyIndicesToJson.get(dg.getBodyId());
            if (bodyJson.get("children")==null)
                bodyJson.put("children", new JSONArray());
            UUID uuid_mesh = addtoFrameJsonObject(dg, geomId, uuid, dgimp.getMat_uuid(), (JSONArray)bodyJson.get("children"));
            vis_uuidList.add(uuid_mesh);
            
            mapUUIDToComponent.put(uuid_mesh, comp);
        }
        mapComponentToUUID.put(comp, vis_uuidList);
        System.out.println("Map component="+comp.getFullPathName()+" to "+vis_uuidList.size());   
 
    }

    private JSONObject loadTemplateJSON() {
        JSONParser parser = new JSONParser();
        JSONObject jsonObject = null;
        String current;
        try {
            current = new java.io.File( "." ).getCanonicalPath();
            System.out.println("Current dir:"+current);
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
        
        try {
            Object obj = parser.parse(new FileReader("threejs/editor/templateScene.json"));
            jsonObject = (JSONObject) obj;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonObject;
    }

    private UUID addtoFrameJsonObject(DecorativeGeometry dg, String geomName, UUID uuid, UUID uuid_mat, JSONArray mobody_objects) {
        Map<String, Object> obj_json = new LinkedHashMap<String, Object>();
        UUID mesh_uuid = UUID.randomUUID();
        obj_json.put("uuid", mesh_uuid.toString());
{'fraction_non_alphanumeric': 0.10868329649510577, 'fraction_numerical': 0.002778654878433849, 'mean_word_length': 3.0141951837769327, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4626195', 'n_tokens_mistral': 4552, 'n_tokens_neox': 4501, 'n_words': 928}