public InternalToken IdentifyCluster(Cluster cluster)
        {
            //Start Stop Watch for statistics
            Stopwatch sw = Stopwatch.StartNew();
             
            InternalToken token = null;
            //Cluster identification Algorithm
            Dictionary<int, TouchInput> clusterPoints = cluster.Points;
            TokenMarker[] meanSquaredTokenReferenceSystem;

            /*Ordered indexes of markers 0 => Origin 
            *                            1 => X axis 
            *                            2 => Y axis
            *                            3 => Data
            */
            int[] orderedIndexes = new int[4];

            //Find two furthest apart poits which reppresent the x xis and the y axis markers
            int[] furthestPointIndexes = FindTwoFurthestPoints(clusterPoints.Values.ToArray());
            
            //Gets indexes of two remaing points which reppresent origin and data marker
            int[] originAndDataIndexes = clusterPoints.Where(p => p.Key != furthestPointIndexes[0] && p.Key != furthestPointIndexes[1])
                                                      .Select(z => z.Key).ToArray();

            if(FindOriginIndex(furthestPointIndexes, originAndDataIndexes, clusterPoints, ref orderedIndexes))
            {
                //Origin Marker Identified and stored in orderedIndexes[0]
                if (DistinguishAxisVectors(furthestPointIndexes, clusterPoints, ref orderedIndexes))
                {
                    //Axis markers have been correctly identified
                    //Remaing point is Data Marker
                    orderedIndexes[3] = clusterPoints.Where(p => p.Key != orderedIndexes[0] && p.Key != orderedIndexes[1] && p.Key != orderedIndexes[2])
                                                     .Select(z => z.Key).Single();

                    //Compute Mean Square Problem for reference System

                    Dictionary<int, TokenMarker> markers = TokenUtils.ConvertTouchInputToMarkers(orderedIndexes, clusterPoints);

                    meanSquaredTokenReferenceSystem = TokenUtils.MeanSquareOrthogonalReferenceSystem(markers[orderedIndexes[0]],
                                                                                                     markers[orderedIndexes[1]],
                                                                                                     markers[orderedIndexes[2]],
                                                                                                     TokenManager.CurrentTokenType.DistanceOriginAxisMarkersPX);
                    //Create Token
                    token = new InternalToken(cluster.Hash, markers);
                    token.SetMeanSquareReferenceSystem(meanSquaredTokenReferenceSystem);
                }
                else
                    throw (new TokenAxisNotDistinguishedException("Could not Distinguish Axis"));
            }
            else
            {
                //throw (new NoOrthogonalVectorsFoundException("Could not find Orthogonal Vectors"));
                //No orthogonal vectors found thus no origin, failed identification
                //For the moment return null, in case consider doing second iteration on second maximum
                sw.Stop();
                TokenStatistics.Instance.SetTokenIdentificationTime(sw.ElapsedMilliseconds);
                return token;
            }
            sw.Stop();
            TokenStatistics.Instance.SetTokenIdentificationTime(sw.ElapsedMilliseconds);
            return token;
            
        }
        private void UpdateClusters()
        {
            float minDist = this.ClusterDistThreshold;
            float dist;
            bool minFound = false;
            List<Cluster> clustersList = this.clusters.Values.ToList();

            int mergeCluster1Index = 0;
            int mergeCluster2Index = 0;
            Cluster r1 = new Cluster();
            Cluster r2 = new Cluster();

            if (clusters.Count > 1)
            {
                while(minDist <= this.ClusterDistThreshold)
                {
                    for(int i=0; i < clustersList.Count; i++)
                    {
                        for(int j=i+1; j < clustersList.Count; j++)
                        {
                            Cluster c1 = clustersList.ElementAt(i);
                            Cluster c2 = clustersList.ElementAt(j);

                            dist = Vector2.Distance(c1.Centroid, c2.Centroid);

                            if(dist < minDist)
                            {
                                minDist = dist;
                                mergeCluster1Index = i;
                                mergeCluster2Index = j;
                                r1 = clustersList[i];
                                r2 = clustersList[j];
                                minFound = true;
                            }
                        }
                    }
                    if (minFound)
                    {
                        minFound = false;
                        Cluster mergedCluster = MergeClusters(clustersList.ElementAt(mergeCluster1Index), clustersList.ElementAt(mergeCluster2Index));
                        clustersList.Remove(r1);
                        clustersList.Remove(r2);
                        clustersList.Add(mergedCluster);
                    }
                    else
                        minDist *= 2;
                }

                clusters = clustersList.ToDictionary(v => v.Hash, v => v);
            }
        }
        private void OnInputsUpdateEventHandler(object sender, InputUpdateEventArgs e)
        {
          
            String clusterHash;

            ResetClustersBuffers();
        
            foreach (int touchId in InternalTouches.CancelledTouchBuffer)
            {
                clusterHash = GetClusterIdFromTouchPoint(touchId);
                if (clusterHash != null)
                {
                    //Is a cluster with more than one point
                    if (clusters[clusterHash].PointsIds.Count > 1)
                    {
                        Cluster updatedCluster = clusters[clusterHash].RemovePoint(touchId);
                        //Update Current state Clusters
                        clusters.Remove(clusterHash);
                        clusters.Add(updatedCluster.Hash, updatedCluster);

                        //If State is Cancelled update CancelledCluster Buffer
                        if (updatedCluster.State == ClusterState.Cancelled)
                        {
                            IdentifiedClustersCancelled.Remove(updatedCluster.CancelledClusterHash);
                            IdentifiedClustersCancelled.Add(updatedCluster.CancelledClusterHash, updatedCluster);
                        }
                    }
                    //Is a cluster with only one point
                    else
                    {
                        //Update CancelledClusterBuffer
                        Cluster cluster = clusters[clusterHash].RemovePoint(touchId);
                        if(cluster.State == ClusterState.Cancelled)
                        {
                            IdentifiedClustersCancelled.Remove(cluster.CancelledClusterHash);
                            IdentifiedClustersCancelled.Add(cluster.CancelledClusterHash, cluster);
                        }
                        
                        //Remove cluster from current Clusters
                        clusters.Remove(clusterHash);
                    }
                        
                    
                }
                //Remove touch from fingers touch list

            }

            foreach (int touchId in InternalTouches.MovedTouchBuffer)
            {
                clusterHash = GetClusterIdFromTouchPoint(touchId);
                if (clusterHash != null)
                {
                    Cluster[] updatedCluster = clusters[clusterHash].UpdatePoint(touchId);
                    
                        clusters.Remove(clusterHash);
                    if (updatedCluster[0].Points.Count != 0)
                    {
                        clusters.Add(updatedCluster[0].Hash, updatedCluster[0]);
                        if (updatedCluster[0].State == ClusterState.Cancelled)
                        {
                            IdentifiedClustersCancelled.Remove(updatedCluster[0].CancelledClusterHash);
                            IdentifiedClustersCancelled.Add(updatedCluster[0].CancelledClusterHash, updatedCluster[0]);
                        }
                    }
                    
                    //Its the case where a previous cluster gets separeted into two
                    if (updatedCluster[1] != null)
                        clusters.Add(updatedCluster[1].Hash, updatedCluster[1]);

                }
                else
                {
                    Cluster c = new Cluster(InternalTouches.List[touchId]);
                    clusters.Add(c.Hash, c);
                }
            }


            foreach (int touchId in InternalTouches.BaganTouhBuffer)
            {
                Cluster cl = new Cluster(InternalTouches.List[touchId]);
                clusters.Add(cl.Hash, cl);

            }

            if(InternalTouches.CancelledTouchBuffer.Count > 0 || InternalTouches.MovedTouchBuffer.Count > 0 || InternalTouches.BaganTouhBuffer.Count > 0)
            {
                UpdateClusters();

                CheckClustersUpdated();

                if (IdentifiedClustersCancelled.Count > 0)
                    OnClustersCancelled(new ClusterUpdateEventArgs("Moved cluster request", IdentifiedClustersCancelled.Values.ToList()));

                if (IdentifiedClustersMoved.Count > 0)
                    OnClustersMoved(new ClusterUpdateEventArgs("Moved cluster request", IdentifiedClustersMoved));

                if (ClustersToIdentify.Count > 0)
                    OnClusterToIdentify(new ClusterUpdateEventArgs("Identification request", ClustersToIdentify));

                
                //Get points which are touches and not markers
                InputManager.SetFingersCancelled(InternalTouches.CancelledTouchBuffer.ToArray());

                foreach (Cluster c in clusters.Values)
                {
                    if(c.State == ClusterState.Invalid || c.State == ClusterState.Cancelled)
                    {
                        //This cluster is only made of finger touch points
                        foreach (TouchInput touch in c.Points.Values)
                        {
                            InputManager.AddFingerTouch(touch);
                        }

                    }

                }
            }

        }
        private Cluster MergeClusters(Cluster c1, Cluster c2)
        {
            if (c1.State == ClusterState.Updated || c1.State == ClusterState.Identidied)
            {
                c1.SetCancelledClusterHash(c1.Hash);
                c1.SetCancelledPointIds(c1.PointsIds);
                c1.SetState(ClusterState.Cancelled);
                IdentifiedClustersCancelled.Add(c1.Hash, c1);
            }
            if (c2.State == ClusterState.Updated || c2.State == ClusterState.Identidied)
            {
                c2.SetCancelledClusterHash(c2.Hash);
                c2.SetCancelledPointIds(c2.PointsIds);
                c2.SetState(ClusterState.Cancelled);
                IdentifiedClustersCancelled.Add(c2.Hash, c2);

            }

            List<TouchInput> allPoints = c1.Points.Values.ToList();
            allPoints.AddRange(c2.Points.Values.ToList());

            return new Cluster(allPoints);
        }
Exemple #5
0
        public void Update(Cluster cluster)
        {
            int markerId;
            Vector2 newPostion;
            foreach(KeyValuePair<int,TouchInput> entry in cluster.Points)
            {
                markerId = entry.Key;
                newPostion = entry.Value.Position;

                this.markers[markerId].UpdatePosition(newPostion);
            }

            UpdateMarkersTypeList();
            UpdateTokenAxis();
            UpdateAngle();
            UpdatePosition();

        }
Exemple #6
0
        public Cluster[] UpdatePoint(int touchId)
        {
            Cluster newCluster;
            if (Vector2.Distance(this.Centroid, InternalTouches.List[touchId].Position) < ClusterManager.Instance.ClusterDistThreshold)
            {
                //Point still in clustrer
                _points[touchId] = new TouchInput(touchId, InternalTouches.List[touchId].Position, TouchState.Moved);
                newCluster = null;

                if (State == ClusterState.Identidied)
                    _state = ClusterState.Updated;
            }
            else
            {
                //Point has moved out of the cluster
                //Handle current Cluster

                //If it was just one point then we must cancel the cluster!!!!!!
         //       if (_pointsIds.Count != 1)
         //       {
                    _pointsIds.Remove(touchId);
                    _points.Remove(touchId);

                    if (_state == ClusterState.Identidied || _state == ClusterState.Updated)
                    {
                        _state = ClusterState.Cancelled;
                        _cancelledHash = this.Hash;
                        _cancelledPointsIds.Add(touchId);
                    }

                    else if (State == ClusterState.Cancelled)
                        _cancelledPointsIds.Add(touchId);

                    else if (_pointsIds.Count == 4)
                        _state = ClusterState.Unidentified;

                    else
                        _state = ClusterState.Invalid;

                    //Update new Hash
                    this.Hash = ClusterUtils.GetPointsHash(_pointsIds.ToArray<int>());
         //       }
        //        else
                

                newCluster = new Cluster(InternalTouches.List[touchId]);

            }

            UpdateCentroid();            
            
            return new Cluster[] { this ,newCluster };

        }