fiore@5: /*
fiore@5: CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
fiore@5:
fiore@5: Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
fiore@5:
fiore@5: This program is free software: you can redistribute it and/or modify
fiore@5: it under the terms of the GNU General Public License as published by
fiore@5: the Free Software Foundation, either version 3 of the License, or
fiore@5: (at your option) any later version.
fiore@5:
fiore@5: This program is distributed in the hope that it will be useful,
fiore@5: but WITHOUT ANY WARRANTY; without even the implied warranty of
fiore@5: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
fiore@5: GNU General Public License for more details.
fiore@5:
fiore@5: You should have received a copy of the GNU General Public License
fiore@5: along with this program. If not, see .
fiore@5: */
fiore@5:
fiore@5: #include "CollectionsManager.h"
fiore@5:
fiore@5: using namespace H3DUtil::ArithmeticTypes;
fiore@5:
fiore@5: void CollectionsManager::init(void){
fiore@5: /**************** init jni variables **********************/
fiore@5: // --- classes ---
fiore@5: // get the java haptics class
fiore@5: hapticClass = env->GetObjectClass(*haptics);
fiore@5: if(hapticClass == NULL){
fiore@5: stopExecution("Could not find the Haptics class");
fiore@5: }
fiore@5:
fiore@5: bitsetClass = env->FindClass("Ljava/util/BitSet;");
fiore@5: if(bitsetClass == NULL)
fiore@5: stopExecution("failed to find bitset class");
fiore@5:
fiore@5: //get the node list class
fiore@5: listClass = env->FindClass("Ljava/util/ArrayList;");
fiore@5: if(listClass == NULL)
fiore@5: stopExecution("failed to find list class");
fiore@5:
fiore@5: // get the Node class to call the get method on the node list
fiore@5: hapticNodeClass = env->FindClass("Luk/ac/qmul/eecs/ccmi/haptics/Node;");
fiore@5: if(hapticNodeClass == NULL){
fiore@5: stopExecution("Could not find the Node class");
fiore@5: }
fiore@5:
fiore@5: // get the Edge class to call the get method on the edge list
fiore@5: hapticEdgeClass = env->FindClass("Luk/ac/qmul/eecs/ccmi/haptics/Edge;");
fiore@5: if(hapticEdgeClass == NULL){
fiore@5: stopExecution("Could not find the Edge class");
fiore@5: }
fiore@5: // --- methods ---
fiore@5: // "get" method id
fiore@5: getMethodId = env->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;");
fiore@5: if(getMethodId == NULL)
fiore@5: stopExecution("Could not retrieve the get method id");
fiore@5:
fiore@5: //size method id
fiore@5: sizeMethodId = env->GetMethodID(listClass, "size", "()I");
fiore@5: if(sizeMethodId == NULL)
fiore@5: stopExecution("failed to get size method id");
fiore@5:
fiore@5: //get method of the BitSet class
fiore@5: getBitMethodId = env->GetMethodID(bitsetClass, "get","(I)Z");
fiore@5: if(getBitMethodId == NULL)
fiore@5: stopExecution("failed to get the get method id of the BitSet class");
fiore@5:
fiore@5: // -- field id's --
fiore@5: //retrieve edgeList field id
fiore@5: edgeListfieldId = env->GetFieldID(hapticClass,"currentEdges", "Ljava/util/ArrayList;");
fiore@5: if(edgeListfieldId == NULL){
fiore@5: stopExecution("failed to find the edge list field id");
fiore@5: }
fiore@5:
fiore@5: //retrieve nodeList field id
fiore@5: nodeListfieldId = env->GetFieldID(hapticClass,"currentNodes", "Ljava/util/ArrayList;");
fiore@5: if(nodeListfieldId == NULL){
fiore@5: stopExecution("failed to find the node list field id");
fiore@5: }
fiore@5:
fiore@5: // Node fields id's
fiore@5: xFieldId = env->GetFieldID(hapticNodeClass,"x","D");
fiore@5: if(xFieldId == NULL)
fiore@5: stopExecution("Could not find the x field ID");
fiore@5:
fiore@5:
fiore@5: yFieldId = env->GetFieldID(hapticNodeClass,"y","D");
fiore@5: if(yFieldId == NULL)
fiore@5: stopExecution("Could not find the y field ID");
fiore@5:
fiore@5: nodeHapticIdFieldId = env->GetFieldID(hapticNodeClass, "hapticId", "I");
fiore@5: if(nodeHapticIdFieldId == NULL)
fiore@5: stopExecution("Could not find the node hapticId field ID");
fiore@5:
fiore@5: nodeDiagramIdFieldId = env->GetFieldID(hapticNodeClass, "diagramId", "I");
fiore@5: if(nodeDiagramIdFieldId == NULL)
fiore@5: stopExecution("Could not find the node diagramId field ID");
fiore@5:
fiore@5: // Edge field id's
fiore@5: // edge.hapticId
fiore@5: edgeHapticIdFieldId = env->GetFieldID(hapticEdgeClass, "hapticId", "I");
fiore@5: if(edgeHapticIdFieldId == NULL)
fiore@5: stopExecution("Could not find the edge hapticId field ID");
fiore@5:
fiore@5: edgeDiagramIdFieldId = env->GetFieldID(hapticEdgeClass, "diagramId", "I");
fiore@5: if(edgeDiagramIdFieldId == NULL)
fiore@5: stopExecution("Could not find the edge diagramId field ID");
fiore@5:
fiore@5: // stipplePattern
fiore@5: stipplePatternfieldId = env->GetFieldID(hapticEdgeClass, "stipplePattern", "I");
fiore@5: if(stipplePatternfieldId == NULL){
fiore@5: stopExecution("Could not find the stipplePattern field ID");
fiore@5: }
fiore@5:
fiore@5: edgeSizefieldId = env->GetFieldID(hapticEdgeClass, "size", "I");
fiore@5: if(edgeSizefieldId == NULL)
fiore@5: stopExecution("Could not find edge size field ID");
fiore@5:
fiore@5: edgeXsFieldId = env->GetFieldID(hapticEdgeClass,"xs", "[D");
fiore@5: if(edgeXsFieldId == NULL)
fiore@5: stopExecution("Could not find edge xs field ID");
fiore@5:
fiore@5: edgeYsFieldId = env->GetFieldID(hapticEdgeClass,"ys", "[D");
fiore@5: if(edgeYsFieldId == NULL)
fiore@5: stopExecution("Could not find edge ys field ID");
fiore@5:
fiore@5: edgeAdjMatrixFieldId = env->GetFieldID(hapticEdgeClass,"adjMatrix", "[Ljava/util/BitSet;");
fiore@5: if(edgeAdjMatrixFieldId == NULL)
fiore@5: stopExecution("Could not find edge adjMatrix field ID");
fiore@5:
fiore@5: attractPointXFieldId = env->GetFieldID(hapticEdgeClass, "attractPointX", "D");
fiore@5: if(attractPointXFieldId == NULL)
fiore@5: stopExecution("Could not find the edge attractPointX field ID");
fiore@5:
fiore@5: attractPointYFieldId = env->GetFieldID(hapticEdgeClass, "attractPointY", "D");
fiore@5: if(attractPointYFieldId == NULL)
fiore@5: stopExecution("Could not find the edge attractPointY field ID");
fiore@5:
fiore@5: edgeNodeStartFieldId = env->GetFieldID(hapticEdgeClass, "nodeStart", "I");
fiore@5: if(edgeNodeStartFieldId == NULL)
fiore@5: stopExecution("Could not find the edge nodeStart field ID");
fiore@5: }
fiore@5:
fiore@5: const jint CollectionsManager::getNodesNum() {
fiore@5: /* to read the node list field into the nodeList variable each time we get the size is *
fiore@5: * needed as, when the tab is switched the nodeList variables still points to the previuos *
fiore@5: * tab's node list. We do it only here and not in getNodeData because getNodesData *
fiore@5: * follows this call before releasing the monitor, therefore data integrity is granted. */
fiore@5: env->DeleteLocalRef(nodeList);
fiore@5: nodeList = env->GetObjectField(*haptics, nodeListfieldId);
fiore@5: if(nodeList == NULL){
fiore@5: stopExecution("could not get the node list field of Haptic Class");
fiore@5: }
fiore@5: jint size = env->CallIntMethod( nodeList, sizeMethodId);
fiore@5: checkExceptions(env,"Could not call ArrayList.size()");
fiore@5: return size;
fiore@5: }
fiore@5:
fiore@5: const jint CollectionsManager::getEdgesNum(){
fiore@5: env->DeleteLocalRef(edgeList);
fiore@5: edgeList = env->GetObjectField(*haptics, edgeListfieldId);
fiore@5: if(edgeList == NULL){
fiore@5: stopExecution("could not get the edge list field of Haptic Class");
fiore@5: }
fiore@5:
fiore@5: jint size = env->CallIntMethod( edgeList, sizeMethodId);
fiore@5: checkExceptions(env, "Could not call ArrayList.size()");
fiore@5: return size;
fiore@5: }
fiore@5:
fiore@5: CollectionsManager::NodeData & CollectionsManager::getNodeData(const int i){
fiore@5: /* get the i-th node */
fiore@5: jobject currentNode = env->CallObjectMethod(nodeList,getMethodId,i);
fiore@5: checkExceptions(env,"Could not call ArrayList.size()");
fiore@5: fillupNodeData(nd,currentNode);
fiore@5: env->DeleteLocalRef(currentNode);
fiore@5: return nd;
fiore@5: }
fiore@5:
fiore@5: CollectionsManager::EdgeData & CollectionsManager::getEdgeData(const int i){
fiore@5: /* first we look for the i-th edge in the Haptics java class. Once we get it, *
fiore@5: * we need all the coordinates of the node this edge is connecting, so that we *
fiore@5: * can draw it. The edge mantains a list of references to such nodes. */
fiore@5:
fiore@5: /* get the i-th edge */
fiore@5: jobject currentEdge = env->CallObjectMethod(edgeList,getMethodId,i);
fiore@5: checkExceptions(env, "Could not call ArrayList.get(int) in the haptics edges");
fiore@5: if(currentEdge == NULL)
fiore@5: stopExecution("Could not find get current Edge");
fiore@5: jint size = env->GetIntField(currentEdge, edgeSizefieldId);
fiore@5: ed.setSize(size);
fiore@5: fillupEdgeData(ed,currentEdge);
fiore@5: env->DeleteLocalRef(currentEdge);
fiore@5: return ed;
fiore@5: }
fiore@5:
fiore@5: void CollectionsManager::fillupNodeData(NodeData & nd, jobject & currentNode){
fiore@5: //reads the fields of the current node
fiore@5: nd.x = env->GetDoubleField(currentNode,xFieldId);
fiore@5: nd.y = env->GetDoubleField(currentNode,yFieldId);
fiore@5: // takes coordinates from the screen. Needs to convert the y axis as in openGL (0,0) = bottom left corner
fiore@5: Vec3d & glCoordinatePosition = screenToHapticSpace(Vec3d(nd.x, nd.y, 0),screenWidth,screenHeight);
fiore@5: nd.x = glCoordinatePosition[0];
fiore@5: nd.y = glCoordinatePosition[1];
fiore@5: nd.hapticId = env->GetIntField(currentNode, nodeHapticIdFieldId);
fiore@5: nd.diagramId = env->GetIntField(currentNode, nodeDiagramIdFieldId);
fiore@5: }
fiore@5:
fiore@5: void CollectionsManager::fillupEdgeData(EdgeData & ed, jobject & currentEdge){
fiore@5: /* get the array of x coordinates */
fiore@5: jobject xsAsObj = env->GetObjectField(currentEdge,edgeXsFieldId);
fiore@5: if(xsAsObj == NULL)
fiore@5: stopExecution("Cannot get the xs field");
fiore@5: jdoubleArray *jxs = reinterpret_cast(&xsAsObj);
fiore@5: double * xs = env->GetDoubleArrayElements(*jxs, NULL);
fiore@5: if(xs == NULL)
fiore@5: stopExecution("Cannot get the xs field array of double");
fiore@5:
fiore@5: /* get the array of y coordinates */
fiore@5: jobject ysAsObj = env->GetObjectField(currentEdge,edgeYsFieldId);
fiore@5: if(ysAsObj == NULL)
fiore@5: stopExecution("Cannot get the xs field");
fiore@5:
fiore@5: jdoubleArray *jys = reinterpret_cast(&ysAsObj);
fiore@5: double * ys = env->GetDoubleArrayElements(*jys, NULL);
fiore@5: if(ys == NULL)
fiore@5: stopExecution("Cannot get the ys field array of double");
fiore@5: // copy the data into the edgeData object
fiore@5: for(unsigned int i=0; iReleaseDoubleArrayElements(*jxs, xs, 0);
fiore@5: env->ReleaseDoubleArrayElements(*jys, ys, 0);
fiore@5: env->DeleteLocalRef(xsAsObj);
fiore@5: env->DeleteLocalRef(ysAsObj);
fiore@5: jobject adjMatrixAsObj = env->GetObjectField(currentEdge, edgeAdjMatrixFieldId);
fiore@5: if(adjMatrixAsObj == NULL)
fiore@5: stopExecution("Cannot get the adjMatrix field");
fiore@5: jobjectArray *jadjMatrix = reinterpret_cast(&adjMatrixAsObj);
fiore@5:
fiore@5: for(unsigned int i=0; iGetObjectArrayElement(*jadjMatrix,i);
fiore@5: if(adjMatrixBitSet == NULL)
fiore@5: stopExecution("Cannot get the adjMatrix field array element");
fiore@5: for(unsigned int j=0;jCallBooleanMethod(adjMatrixBitSet,getBitMethodId,j);
fiore@5: checkExceptions(env,"Could not call BitSet.get()");
fiore@5: if(b == JNI_TRUE)
fiore@5: ed.adjMatrix[i][j] = true;
fiore@5: else
fiore@5: ed.adjMatrix[i][j] = false;
fiore@5: }
fiore@5: env->DeleteLocalRef(adjMatrixBitSet);
fiore@5: }
fiore@5: env->DeleteLocalRef(adjMatrixAsObj);
fiore@5:
fiore@5: // set the haptic id used by the haptic device
fiore@5: ed.hapticId = env->GetIntField(currentEdge, edgeHapticIdFieldId);
fiore@5: // set the diagram id used in the java thread
fiore@5: ed.diagramId = env->GetIntField(currentEdge, edgeDiagramIdFieldId);
fiore@5: // set the stipple pattern
fiore@5: ed.stipplePattern = env->GetIntField(currentEdge, stipplePatternfieldId);
fiore@5: // set the attract point
fiore@5: ed.attractPoint[0] = env->GetDoubleField(currentEdge, attractPointXFieldId);
fiore@5: ed.attractPoint[1] = env->GetDoubleField(currentEdge, attractPointYFieldId);
fiore@5: Vec3d & glCoordinatePosition = screenToHapticSpace(Vec3d(ed.attractPoint[0], ed.attractPoint[1], 0),screenWidth,screenHeight);
fiore@5: ed.attractPoint[0] = glCoordinatePosition[0];
fiore@5: ed.attractPoint[1] = glCoordinatePosition[1];
fiore@5: //set the index from which the nodes start in the adjMatrix
fiore@5: ed.nodeStart = env->GetIntField(currentEdge, edgeNodeStartFieldId);
fiore@5: }