view native/Falcon/CollectionsManager.cpp @ 8:ea7885bd9bff tip

fixed bug : render solid line as dotted/dashed when moving the stylus from dotted/dashed to solid
author ccmi-guest
date Thu, 03 Jul 2014 16:12:20 +0100
parents d66dd5880081
children
line wrap: on
line source
/*  
 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
  
 Copyright (C) 2011  Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/  

#include "CollectionsManager.h"

using namespace H3DUtil::ArithmeticTypes;

void CollectionsManager::init(void){
	/**************** init jni variables **********************/
	// --- classes --- 
	// get the java haptics class 
	hapticClass = env->GetObjectClass(*haptics);
	if(hapticClass == NULL){
		stopExecution("Could not find the Haptics class");
	}
	
	bitsetClass = env->FindClass("Ljava/util/BitSet;");
	if(bitsetClass == NULL)
		stopExecution("failed to find bitset class");

	//get the node list class 
	listClass = env->FindClass("Ljava/util/ArrayList;");
	if(listClass == NULL)
		stopExecution("failed to find list class");

	// get the Node class to call the get method on the node list 
	hapticNodeClass = env->FindClass("Luk/ac/qmul/eecs/ccmi/haptics/Node;");
	if(hapticNodeClass == NULL){
		stopExecution("Could not find the Node class");
	}

	// get the Edge class to call the get method on the edge list 
	hapticEdgeClass = env->FindClass("Luk/ac/qmul/eecs/ccmi/haptics/Edge;");
	if(hapticEdgeClass == NULL){
		stopExecution("Could not find the Edge class");
	}
	// --- methods ---
	// "get" method id 
	getMethodId = env->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;");
	if(getMethodId == NULL)
		stopExecution("Could not retrieve the get method id");

	//size method id
	sizeMethodId = env->GetMethodID(listClass, "size", "()I");
	if(sizeMethodId == NULL)
		stopExecution("failed to get size method id");

	//get method of the BitSet class
	getBitMethodId = env->GetMethodID(bitsetClass, "get","(I)Z");
	if(getBitMethodId == NULL)
		stopExecution("failed to get the get method id of the BitSet class");

	// -- field id's --
	//retrieve edgeList field id
	edgeListfieldId = env->GetFieldID(hapticClass,"currentEdges", "Ljava/util/ArrayList;");
	if(edgeListfieldId == NULL){
		stopExecution("failed to find the edge list field id"); 
	}
	
	//retrieve nodeList field id
	nodeListfieldId = env->GetFieldID(hapticClass,"currentNodes", "Ljava/util/ArrayList;");
	if(nodeListfieldId == NULL){
		stopExecution("failed to find the node list field id");
	}

	// Node fields id's 
	xFieldId = env->GetFieldID(hapticNodeClass,"x","D");
	if(xFieldId == NULL)
		stopExecution("Could not find the x field ID");
	

	yFieldId = env->GetFieldID(hapticNodeClass,"y","D");
	if(yFieldId == NULL)
		stopExecution("Could not find the y field ID");
	
	nodeHapticIdFieldId = env->GetFieldID(hapticNodeClass, "hapticId", "I");
	if(nodeHapticIdFieldId == NULL)
		stopExecution("Could not find the node hapticId field ID");

	nodeDiagramIdFieldId = env->GetFieldID(hapticNodeClass, "diagramId", "I");
	if(nodeDiagramIdFieldId == NULL) 
		stopExecution("Could not find the node diagramId field ID");
	
	// Edge field id's
	// edge.hapticId
	edgeHapticIdFieldId = env->GetFieldID(hapticEdgeClass, "hapticId", "I");
	if(edgeHapticIdFieldId == NULL)
		stopExecution("Could not find the edge hapticId field ID");

	edgeDiagramIdFieldId = env->GetFieldID(hapticEdgeClass, "diagramId", "I");
	if(edgeDiagramIdFieldId == NULL)
		stopExecution("Could not find the edge diagramId field ID");

	// stipplePattern
	stipplePatternfieldId = env->GetFieldID(hapticEdgeClass, "stipplePattern", "I");
	if(stipplePatternfieldId == NULL){
		stopExecution("Could not find the stipplePattern field ID");
	}

	edgeSizefieldId = env->GetFieldID(hapticEdgeClass, "size", "I");
	if(edgeSizefieldId == NULL)
		stopExecution("Could not find edge size field ID");

	edgeXsFieldId = env->GetFieldID(hapticEdgeClass,"xs", "[D");
	if(edgeXsFieldId == NULL)
		stopExecution("Could not find edge xs field ID");
	
	edgeYsFieldId = env->GetFieldID(hapticEdgeClass,"ys", "[D");
	if(edgeYsFieldId == NULL)
		stopExecution("Could not find edge ys field ID");

	edgeAdjMatrixFieldId = env->GetFieldID(hapticEdgeClass,"adjMatrix", "[Ljava/util/BitSet;");
	if(edgeAdjMatrixFieldId == NULL)
		stopExecution("Could not find edge adjMatrix field ID");

	attractPointXFieldId = env->GetFieldID(hapticEdgeClass, "attractPointX", "D");
	if(attractPointXFieldId == NULL) 
		stopExecution("Could not find the edge attractPointX field ID");

	attractPointYFieldId = env->GetFieldID(hapticEdgeClass, "attractPointY", "D");
	if(attractPointYFieldId == NULL) 
		stopExecution("Could not find the edge attractPointY field ID");

	edgeNodeStartFieldId = env->GetFieldID(hapticEdgeClass, "nodeStart", "I");
	if(edgeNodeStartFieldId == NULL)
		stopExecution("Could not find the edge nodeStart field ID");
}

const jint CollectionsManager::getNodesNum() {
	/* to read the node list field into the nodeList variable each time we get the size is     *
	 * needed as, when the tab is switched the nodeList variables still points to the previuos *
	 * tab's node list. We do it only here and not in getNodeData because  getNodesData        *
	 * follows this call before releasing the monitor, therefore data integrity is granted.    */
	env->DeleteLocalRef(nodeList);
	nodeList = env->GetObjectField(*haptics, nodeListfieldId);
	if(nodeList == NULL){
		stopExecution("could not get the node list field of Haptic Class");
	}
	jint size =  env->CallIntMethod( nodeList, sizeMethodId);
	checkExceptions(env,"Could not call ArrayList<Node>.size()");
	return size;
}

const jint CollectionsManager::getEdgesNum(){
	env->DeleteLocalRef(edgeList);
	edgeList = env->GetObjectField(*haptics, edgeListfieldId);
	if(edgeList == NULL){
		stopExecution("could not get the edge list field of Haptic Class");
	}

	jint size = env->CallIntMethod( edgeList, sizeMethodId);
	checkExceptions(env, "Could not call ArrayList<Edge>.size()");
	return size;
}

CollectionsManager::NodeData & CollectionsManager::getNodeData(const int i){
	/* get the i-th node */
	jobject currentNode = env->CallObjectMethod(nodeList,getMethodId,i);
	checkExceptions(env,"Could not call ArrayList<Node>.size()");
	fillupNodeData(nd,currentNode); 
	env->DeleteLocalRef(currentNode);
	return nd;
}

CollectionsManager::EdgeData & CollectionsManager::getEdgeData(const int i){
	/* first we look for the i-th edge in the Haptics java class. Once we get it,  *
	 * we need all the coordinates of the node this edge is connecting, so that we *
	 * can draw it. The edge mantains a list of references to such nodes.          */

	/* get the i-th edge */
	jobject currentEdge = env->CallObjectMethod(edgeList,getMethodId,i);
	checkExceptions(env, "Could not call ArrayList<Edge>.get(int) in the haptics edges");
	if(currentEdge == NULL)
		stopExecution("Could not find get current Edge");
	jint size = env->GetIntField(currentEdge, edgeSizefieldId);
	ed.setSize(size); 
	fillupEdgeData(ed,currentEdge);	
	env->DeleteLocalRef(currentEdge);
	return ed;
}

void CollectionsManager::fillupNodeData(NodeData & nd, jobject & currentNode){
	//reads the fields of the current node 
	nd.x = env->GetDoubleField(currentNode,xFieldId);
	nd.y = env->GetDoubleField(currentNode,yFieldId);
	// takes coordinates from the screen. Needs to convert the y axis as in openGL (0,0) = bottom left corner
	Vec3d & glCoordinatePosition = screenToHapticSpace(Vec3d(nd.x, nd.y, 0),screenWidth,screenHeight);
	nd.x = glCoordinatePosition[0];
	nd.y = glCoordinatePosition[1];
	nd.hapticId = env->GetIntField(currentNode, nodeHapticIdFieldId);
	nd.diagramId = env->GetIntField(currentNode, nodeDiagramIdFieldId);
}

void CollectionsManager::fillupEdgeData(EdgeData & ed, jobject & currentEdge){
	/* get the array of x coordinates */
	jobject xsAsObj = env->GetObjectField(currentEdge,edgeXsFieldId);
	if(xsAsObj == NULL)
		stopExecution("Cannot get the xs field");
	jdoubleArray *jxs = reinterpret_cast<jdoubleArray*>(&xsAsObj);
	double * xs = env->GetDoubleArrayElements(*jxs, NULL);
	if(xs == NULL)
		stopExecution("Cannot get the xs field array of double");

	/* get the array of y coordinates */
	jobject ysAsObj = env->GetObjectField(currentEdge,edgeYsFieldId);
	if(ysAsObj == NULL)
		stopExecution("Cannot get the xs field");
		
	jdoubleArray *jys = reinterpret_cast<jdoubleArray*>(&ysAsObj);
	double * ys = env->GetDoubleArrayElements(*jys, NULL);
	if(ys == NULL)
		stopExecution("Cannot get the ys field array of double");
	// copy the data into the edgeData object
	for(unsigned int i=0; i<ed.getSize(); i++){ 
		ed.x[i] = xs[i];
		ed.y[i] = ys[i];
		// takes coordinates from the screen (needs to convert the y axis as in openGL 0 = bottom left corner
		Vec3d & glCoordinatePosition = screenToHapticSpace(Vec3d(ed.x[i], ed.y[i], 0),screenWidth,screenHeight);
		ed.x[i] = glCoordinatePosition[0];
		ed.y[i] = glCoordinatePosition[1];
	}
	env->ReleaseDoubleArrayElements(*jxs, xs, 0);
	env->ReleaseDoubleArrayElements(*jys, ys, 0);
	env->DeleteLocalRef(xsAsObj);
	env->DeleteLocalRef(ysAsObj);
	jobject adjMatrixAsObj = env->GetObjectField(currentEdge, edgeAdjMatrixFieldId);
	if(adjMatrixAsObj == NULL)
		stopExecution("Cannot get the adjMatrix field");
	jobjectArray *jadjMatrix = reinterpret_cast<jobjectArray*>(&adjMatrixAsObj);
	
	for(unsigned int i=0; i<ed.getSize(); i++){
		jobject adjMatrixBitSet = env->GetObjectArrayElement(*jadjMatrix,i);
		if(adjMatrixBitSet == NULL)
			stopExecution("Cannot get the adjMatrix field array element");
		for(unsigned int j=0;j<ed.getSize(); j++){
			jboolean b = env->CallBooleanMethod(adjMatrixBitSet,getBitMethodId,j);
			checkExceptions(env,"Could not call BitSet.get()");
			if(b == JNI_TRUE)
				ed.adjMatrix[i][j] = true;
			else
				ed.adjMatrix[i][j] = false;
		}
		env->DeleteLocalRef(adjMatrixBitSet);
	}	
	env->DeleteLocalRef(adjMatrixAsObj);

	// set the haptic id used by the haptic device 
	ed.hapticId = env->GetIntField(currentEdge, edgeHapticIdFieldId);
	// set the diagram id used in the java thread
	ed.diagramId = env->GetIntField(currentEdge, edgeDiagramIdFieldId);
	// set the stipple pattern 
	ed.stipplePattern = env->GetIntField(currentEdge, stipplePatternfieldId);
	// set the attract point
	ed.attractPoint[0] = env->GetDoubleField(currentEdge, attractPointXFieldId);
	ed.attractPoint[1] = env->GetDoubleField(currentEdge, attractPointYFieldId);
	Vec3d & glCoordinatePosition = screenToHapticSpace(Vec3d(ed.attractPoint[0], ed.attractPoint[1], 0),screenWidth,screenHeight);
	ed.attractPoint[0] = glCoordinatePosition[0];
	ed.attractPoint[1] = glCoordinatePosition[1];
	//set the index from which the nodes start in the adjMatrix
	ed.nodeStart = env->GetIntField(currentEdge, edgeNodeStartFieldId);
}