예제 #1
0
        private void computeAndRegisterClusterPoint(
            LineSegmentCluster clusterEntry,
            double currValue,
            HashSet <int> lineSegments)
        {
            int     nLineSegmentsInSet = lineSegments.Count;
            Point2D clusterPoint       = new Point2D(0, 0);
            Point2D sweepPoint         = new Point2D(0, 0);

            foreach (int iter in lineSegments)
            {
                // get the sweep point of each line segment
                // this point is parallel to the current value of the sweeping direction
                sweepPoint    = getSweepPointOfLineSegment(clusterEntry, currValue, iter);
                clusterPoint += sweepPoint / (double)nLineSegmentsInSet;
            }

            // NOTE: this program code works only for the 2-dimensional data
            double x = GET_X_REV_ROTATION(clusterPoint.x, clusterPoint.y, clusterEntry.cosTheta, clusterEntry.sinTheta);
            double y = GET_Y_REV_ROTATION(clusterPoint.x, clusterPoint.y, clusterEntry.cosTheta, clusterEntry.sinTheta);

            // register the obtained cluster point (i.e., the average of all the sweep points)
            clusterEntry.clusterPointArray.Add(new Point2D(x, y));

            return;
        }
예제 #2
0
        private Point2D getSweepPointOfLineSegment(LineSegmentCluster clusterEntry,
                                                   double currValue, int lineSegmentId)
        {
            Segment lineSegmentPoint = m_lineSegmentPointArray[lineSegmentId];     //  2n-dimensional point

            //  NOTE: this program code works only for the 2-dimensional data
            double newStartX, newEndX, newStartY, newEndY;

            newStartX = GET_X_ROTATION(lineSegmentPoint.start.x, lineSegmentPoint.start.y, clusterEntry.cosTheta, clusterEntry.sinTheta);
            newEndX   = GET_X_ROTATION(lineSegmentPoint.end.x, lineSegmentPoint.end.y, clusterEntry.cosTheta, clusterEntry.sinTheta);
            newStartY = GET_Y_ROTATION(lineSegmentPoint.start.x, lineSegmentPoint.start.y, clusterEntry.cosTheta, clusterEntry.sinTheta);
            newEndY   = GET_Y_ROTATION(lineSegmentPoint.end.x, lineSegmentPoint.end.y, clusterEntry.cosTheta, clusterEntry.sinTheta);

            double coefficient = (currValue - newStartX) / (newEndX - newStartX);

            return(new Point2D(currValue, newStartY + coefficient * (newEndY - newStartY)));
        }
예제 #3
0
        private void RegisterAndUpdateLineSegmentCluster(int componentId, int lineSegmentId)
        {
            LineSegmentCluster clusterEntry = m_lineSegmentClusters[componentId];

            //  the start and end values of the first dimension (e.g., the x value in the 2-dimension)
            //  NOTE: this program code works only for the 2-dimensional data

            Segment aLineSegment   = m_lineSegmentPointArray[lineSegmentId];
            double  orderingValue1 = GET_X_ROTATION(aLineSegment.start.x,
                                                    aLineSegment.start.y, clusterEntry.cosTheta, clusterEntry.sinTheta);
            double orderingValue2 = GET_X_ROTATION(aLineSegment.end.x,
                                                   aLineSegment.end.y, clusterEntry.cosTheta, clusterEntry.sinTheta);

            CandidateClusterPoint existingCandidatePoint, newCandidatePoint1, newCandidatePoint2;
            int i, j;
            //  sort the line segment points by the coordinate of the first dimension
            //  simply use the insertion sort algorithm
            //  START ...
            int iter1 = 0;

            for (i = 0; i < clusterEntry.candidatePointList.Count; i++)
            {
                existingCandidatePoint = clusterEntry.candidatePointList[iter1];
                if (existingCandidatePoint.orderingValue >= orderingValue1)
                {
                    break;
                }
                iter1++;
            }
            newCandidatePoint1 = new CandidateClusterPoint();

            newCandidatePoint1.orderingValue  = orderingValue1;
            newCandidatePoint1.lineSegmentId  = lineSegmentId;
            newCandidatePoint1.startPointFlag = true;
            if (i == 0)
            {
                clusterEntry.candidatePointList.Insert(0, newCandidatePoint1);
            }
            else if (i >= clusterEntry.candidatePointList.Count)
            {
                clusterEntry.candidatePointList.Add(newCandidatePoint1);
            }
            else
            {
                clusterEntry.candidatePointList.Insert(iter1, newCandidatePoint1);
            }
            int iter2 = 0;

            for (j = 0; j < clusterEntry.candidatePointList.Count; j++)
            {
                existingCandidatePoint = clusterEntry.candidatePointList[iter2];
                if (existingCandidatePoint.orderingValue >= orderingValue2)
                {
                    break;
                }
                iter2++;
            }

            newCandidatePoint2 = new CandidateClusterPoint();
            newCandidatePoint2.orderingValue  = orderingValue2;
            newCandidatePoint2.lineSegmentId  = lineSegmentId;
            newCandidatePoint2.startPointFlag = false;

            if (j == 0)
            {
                clusterEntry.candidatePointList.Insert(0, newCandidatePoint2);
            }
            else if (j >= clusterEntry.candidatePointList.Count)
            {
                clusterEntry.candidatePointList.Add(newCandidatePoint2);
            }
            else
            {
                clusterEntry.candidatePointList.Insert(iter2, newCandidatePoint2);
            }
            //  ... END

            int trajectoryId = m_idArray[lineSegmentId].trajectoryId;

            //  store the identifier of the trajectories that belong to this line segment cluster
            if (!clusterEntry.trajectoryIdList.Contains(trajectoryId))
            {
                clusterEntry.trajectoryIdList.Add(trajectoryId);
                clusterEntry.nTrajectories++;
            }
            return;
        }
예제 #4
0
        private void computeRepresentativeLines(LineSegmentCluster clusterEntry)
        {
            HashSet <int> lineSegments  = new HashSet <int>();
            HashSet <int> insertionList = new HashSet <int>();
            HashSet <int> deletionList  = new HashSet <int>();

            int iter = 0;
            CandidateClusterPoint candidatePoint, nextCandidatePoint;
            double prevOrderingValue = 0.0;

            int nClusterPoints       = 0;

            lineSegments.Clear();

            //  sweep the line segments in a line segment cluster

            while (iter != (clusterEntry.candidatePointList.Count - 1) && clusterEntry.candidatePointList.Count > 0)
            {
                insertionList.Clear();
                deletionList.Clear();

                do
                {
                    candidatePoint = clusterEntry.candidatePointList[iter];
                    iter++;
                    //  check whether this line segment has begun or not
                    if (!lineSegments.Contains(candidatePoint.lineSegmentId))
                    {
                        // iter1 = lineSegments.find(candidatePoint.lineSegmentId);
                        // if (iter1 == lineSegments.end())	{				//  if there is no matched element,
                        insertionList.Add(candidatePoint.lineSegmentId);        //  this line segment begins at this point
                        lineSegments.Add(candidatePoint.lineSegmentId);
                    }
                    else                                                //  if there is a matched element,
                    {
                        deletionList.Add(candidatePoint.lineSegmentId); //  this line segment ends at this point
                    }
                    //  check whether the next line segment begins or ends at the same point
                    if (iter != (clusterEntry.candidatePointList.Count - 1))
                    {
                        nextCandidatePoint = clusterEntry.candidatePointList[iter];
                    }
                    else
                    {
                        break;
                    }
                } while (candidatePoint.orderingValue == nextCandidatePoint.orderingValue);

                //  check if a line segment is connected to another line segment in the same trajectory
                //  if so, delete one of the line segments to remove duplicates
                foreach (int a in insertionList)
                {
                    foreach (int b in deletionList)
                    {
                        if (m_idArray[a].trajectoryId
                            == m_idArray[b].trajectoryId)
                        {
                            lineSegments.Remove(b);
                            deletionList.Remove(b);
                            break;
                        }
                    }
                }

                // if the current density exceeds a given threshold
                if (lineSegments.Count >= m_parameter.minLnsParam)
                {
                    if (Math.Abs(candidatePoint.orderingValue - prevOrderingValue) > ((double)m_parameter.minSegmentLength / 1.414))
                    {
                        computeAndRegisterClusterPoint(clusterEntry, candidatePoint.orderingValue, lineSegments);
                        prevOrderingValue = candidatePoint.orderingValue;
                        nClusterPoints++;
                    }
                }

                //  delete the line segment that is not connected to another line segment
                foreach (int b in deletionList)
                {
                    lineSegments.Remove(b);
                }
            }

            if (nClusterPoints >= 2)
            {
                clusterEntry.nClusterPoints = nClusterPoints;
            }
            else
            {
                //  there is no representative trend in this line segment cluster
                clusterEntry.enabled = false;
                clusterEntry.candidatePointList.Clear();
                clusterEntry.clusterPointArray.Clear();
                clusterEntry.trajectoryIdList.Clear();
            }
            return;
        }
예제 #5
0
        bool constructLineSegmentCluster()
        {
            m_lineSegmentClusters = new LineSegmentCluster[m_currComponentId];

            //  initialize the list of line segment clusters
            //  START ...
            for (int i = 0; i < m_currComponentId; i++)
            {
                m_lineSegmentClusters[i] = new LineSegmentCluster();
                m_lineSegmentClusters[i].avgDirectionVector   = new Point2D(0, 0);
                m_lineSegmentClusters[i].lineSegmentClusterId = i;
                m_lineSegmentClusters[i].nLineSegments        = 0;
                m_lineSegmentClusters[i].nClusterPoints       = 0;
                m_lineSegmentClusters[i].nTrajectories        = 0;
                m_lineSegmentClusters[i].enabled = false;
            }
            //  ... END

            //  accumulate the direction vector of a line segment
            for (int i = 0; i < m_nTotalLineSegments; i++)
            {
                int componentId = m_componentIdArray[i];
                if (componentId >= 0)
                {
                    m_lineSegmentClusters[componentId].avgDirectionVector += (m_lineSegmentPointArray[i].end - m_lineSegmentPointArray[i].start);
                    m_lineSegmentClusters[componentId].nLineSegments++;
                }
            }

            //  compute the average direction vector of a line segment cluster
            //  START ...
            double vectorLength1, vectorLength2, innerProduct;
            double cosTheta, sinTheta;

            var m_vector2 = new Point2D(1.0, 0.0);

            for (int i = 0; i < m_currComponentId; i++)
            {
                LineSegmentCluster clusterEntry = m_lineSegmentClusters[i];

                clusterEntry.avgDirectionVector /= (double)clusterEntry.nLineSegments;
                vectorLength1 = clusterEntry.avgDirectionVector.Length();
                vectorLength2 = 1.0;

                innerProduct = clusterEntry.avgDirectionVector.Dot(m_vector2);
                cosTheta     = innerProduct / (vectorLength1 * vectorLength2);
                if (cosTheta > 1.0)
                {
                    cosTheta = 1.0;
                }
                if (cosTheta < -1.0)
                {
                    cosTheta = -1.0;
                }
                sinTheta = Math.Sqrt(1 - Math.Pow(cosTheta, 2));

                if (clusterEntry.avgDirectionVector.y < 0)
                {
                    sinTheta = -sinTheta;
                }

                clusterEntry.cosTheta = cosTheta;
                clusterEntry.sinTheta = sinTheta;
            }
            //  ... END

            //  summarize the information about line segment clusters
            //  the structure for summarization is as follows
            //  [lineSegmentClusterId, nClusterPoints, clusterPointArray, nTrajectories, { trajectoryId, ... }]
            for (int i = 0; i < m_nTotalLineSegments; i++)
            {
                if (m_componentIdArray[i] >= 0)     //  if the componentId < 0, it is a noise
                {
                    RegisterAndUpdateLineSegmentCluster(m_componentIdArray[i], i);
                }
            }

            HashSet <int> trajectories = new HashSet <int>();

            for (int i = 0; i < m_currComponentId; i++)
            {
                LineSegmentCluster clusterEntry = (m_lineSegmentClusters[i]);

                //  a line segment cluster must have trajectories more than the minimum threshold
                if (clusterEntry.nTrajectories >= m_parameter.minLnsParam)
                {
                    clusterEntry.enabled = true;
                    // m_lineSegmentClusters[i].enabled = true;
                    //  DEBUG: count the number of trajectories that belong to clusters
                    for (int j = 0; j < clusterEntry.trajectoryIdList.Count; j++)
                    {
                        trajectories.Add(clusterEntry.trajectoryIdList[j]);
                    }

                    computeRepresentativeLines(clusterEntry);
                    // computeRepresentativeLines(m_lineSegmentClusters[i]);
                }
                else
                {
                    clusterEntry.candidatePointList.Clear();
                    clusterEntry.clusterPointArray.Clear();
                    clusterEntry.trajectoryIdList.Clear();
                }
            }
            //  DEBUG: compute the ratio of trajectories that belong to clusters
            m_document.m_clusterRatio = (double)trajectories.Count / (double)m_document.m_trajectoryList.Count;

            return(true);
        }