private void OnInputsUpdateEventHandler(object sender, InputUpdateEventArgs e)
        {
            Profiler.BeginSample("---ClusterManager : Clusters Update Total");
            String clusterHash;

            ResetClustersBuffers();

            Profiler.BeginSample("------ClusterManager : Cancelled Buffer");
            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

            }
            Profiler.EndSample();

            Profiler.BeginSample("------ClusterManager : Moved Buffer");
            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);
                }
            }
            Profiler.EndSample();

            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)
            {
                Profiler.BeginSample("------ClusterManager : Clusters Update");
                UpdateClusters();
                Profiler.EndSample();

                CheckClustersUpdated();

                if (ClustersToIdentify.Count > 0 || IdentifiedClustersMoved.Count > 0 || IdentifiedClustersCancelled.Count > 0)
                    RaiseClustersUpdateEvent(new ClustersUpdateEventArgs(ClustersToIdentify, IdentifiedClustersMoved, IdentifiedClustersCancelled.Values.ToList()));

                //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);
                        }

                    }

                }
            }

            Profiler.EndSample();
        }
        /// <summary>
        /// Cluster Update hierarchical algorithm 
        /// </summary>
        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);
            }
        }
Esempio n. 3
0
        private void UpdateClusterMoved(Cluster cluster)
        {
            //Update internally the token
            InternalToken internalToken;
            if (tokens.TryGetValue(cluster.Hash, out internalToken))
            {
                internalToken.Update(cluster);
                tokens.Remove(cluster.Hash);
                tokens.Add(internalToken.HashId, internalToken);

                //Update Global Token
                InputManager.GetToken(internalToken.Id).UpdateToken(internalToken, ContinuousMeanSquare);

                //Add token to local buffer
                identifiedTokensMoved.Add(internalToken);
            }
        }
        /// <summary>
        /// Merges 2 clusters together
        /// </summary>
        /// <param name="c1">Cluster 1</param>
        /// <param name="c2">Cluster 2</param>
        /// <returns>Merged cluster</returns>
        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);
        }
Esempio n. 5
0
        private void IdentifyCluster(Cluster cluster)
        {
            //TODO this function requires updates
            Profiler.BeginSample("---TokenEngine : Token Identification");
            InternalToken token = TokenIdentification.Instance.IdentifyCluster(cluster);
            Profiler.EndSample();
            if (token != null)
            {
                //Statistics
                tokenStatistics.TokenIdentification(true);

                //Calculate TokenClass
                Profiler.BeginSample("---TokenEngine: Class LUT");
                token.ComputeTokenClass(ClassComputeRefSystem, ComputeDimension);
                Profiler.EndSample();

                tokenStatistics.TokenClassRecognition(token.Class);

                //Cluster Identification was succesfull

                //Set Token ID
                token.SetTokenId(GetFirstAvailableTokenId());
                tokenIds.Add(token.Id);

                //Add Token to internal List
                tokens.Add(token.HashId, token);

                //Add Token To Global List
                InputManager.AddToken(new Token(token, ContinuousMeanSquare));

                //Add Token TO local buffer
                succesfullyIdentifiedTokens.Add(token);
            }
            else
            {
                tokenStatistics.TokenIdentification(false);

                //Add token to local buffer
                failedIdentifiedCluster.Add(cluster);
            }
        }
Esempio n. 6
0
        private void CancelCluster(Cluster cluster)
        {
            //Cancel cluster according to point
            //Here is very delicate because it must be considered also the possibility of not removing the token untill not all points have been removed
            InternalToken token;
            if (tokens.TryGetValue(cluster.CancelledClusterHash, out token))
            {
                tokenIds.Remove(token.Id);
                InputManager.RemoveToken(token.Id);

                tokens.Remove(cluster.CancelledClusterHash);

                //Add token to local buffer
                identifiedTokensCancelled.Add(token);
            }
        }
Esempio n. 7
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._hashId;
                    _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._hashId = GetPointsHash(_pointsIds.ToArray<int>());
                //       }
                //        else

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

            }

            UpdateCentroid();

            return new Cluster[] { this, newCluster };
        }
        public InternalToken IdentifyCluster(Cluster cluster)
        {
            InternalToken token = null;
            bool originFound, axisDistinguished;
            //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
            Profiler.BeginSample("------Token Identification : Find Two Furthest Point");
            int[] furthestPointIndexes = FindTwoFurthestPoints(clusterPoints.Values.ToArray());
            Profiler.EndSample();

            //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();

            Profiler.BeginSample("------Token Identification : Find Origin");
            originFound = FindOriginIndex(furthestPointIndexes, originAndDataIndexes, clusterPoints, ref orderedIndexes);
            Profiler.EndSample();

            if (originFound)
            {
                //Origin Marker Identified and stored in orderedIndexes[0]
                Profiler.BeginSample("------Token Identification : Distinguish Axis");
                axisDistinguished = DistinguishAxisVectors(furthestPointIndexes, clusterPoints, ref orderedIndexes);
                Profiler.EndSample();

                if (axisDistinguished)
                {
                    //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);

                    Profiler.BeginSample("------Token Identification: MeanSquare Calcs");
                    meanSquaredTokenReferenceSystem = TokenUtils.MeanSquareOrthogonalReferenceSystem(markers[orderedIndexes[0]],
                                                                                                     markers[orderedIndexes[1]],
                                                                                                     markers[orderedIndexes[2]],
                                                                                                     TokenManager.CurrentTokenType.DistanceOriginAxisMarkersPX);
                    Profiler.EndSample();
                    Profiler.BeginSample("------Token Identification: MeanSquare Calcs Maxima");
                    TokenMarker[] meanSquaredTokenReferenceSystemOptimized = TokenUtils.MeanSquareOrthogonalReferenceSystemOptimized(markers[orderedIndexes[0]],
                                                                                                                       markers[orderedIndexes[1]],
                                                                                                                       markers[orderedIndexes[2]],
                                                                                                                       TokenManager.CurrentTokenType.DistanceOriginAxisMarkersPX);

                    Profiler.EndSample();
                    //Create Token
                    token = new InternalToken(cluster.Hash, markers);
                    token.SetMeanSquareReferenceSystem(meanSquaredTokenReferenceSystem);
                }

            }
            else
            {
                //No orthogonal vectors found thus no origin, failed identification
                //For the moment return null, in case consider doing second iteration on second maximum

                return token;
            }

            return token;
        }
        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();

            TokenMarker[] meanSquaredTokenReferenceSystemOptimized = TokenUtils.MeanSquareOrthogonalReferenceSystemOptimized(typeMarkers[MarkerType.Origin],
                                                                                                                             typeMarkers[MarkerType.XAxis],
                                                                                                                             typeMarkers[MarkerType.YAxis],
                                                                                                                             TokenManager.CurrentTokenType.DistanceOriginAxisMarkersPX);
            SetMeanSquareReferenceSystem(meanSquaredTokenReferenceSystemOptimized);
        }