1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "onedimensionalcluster.h"
27 
28 #include <utils/algorithm.h>
29 
30 #include <QDebug>
31 
32 namespace QmlDesigner {
33 
sum(const QList<double> & list)34 double sum(const QList<double> & list)
35 {
36     double sum = 0.0;
37     for (auto iterator = list.constBegin(); iterator != list.constEnd(); ++iterator)
38     {
39         sum += *iterator;
40     }
41 
42     return sum;
43 }
44 
OneDimensionalCluster(const QList<double> & coordinateList)45 OneDimensionalCluster::OneDimensionalCluster(const QList<double> & coordinateList )
46         : m_coordinateList(coordinateList)
47 {
48 }
49 
mean() const50 double OneDimensionalCluster::mean() const
51 {
52     Q_ASSERT(!m_coordinateList.isEmpty());
53 
54     if (m_coordinateList.size() == 1)
55     {
56         return m_coordinateList.constFirst();
57     }
58 
59     return sum(m_coordinateList) / m_coordinateList.size();
60 }
61 
constFirst() const62 double OneDimensionalCluster::constFirst() const
63 {
64     Q_ASSERT(!m_coordinateList.isEmpty());
65 
66     return m_coordinateList.constFirst();
67 }
68 
createOneDimensionalClusterList(const QList<double> & oneDimensionalCoordinateList)69 QList<OneDimensionalCluster> OneDimensionalCluster::createOneDimensionalClusterList(const QList<double> & oneDimensionalCoordinateList)
70 {
71     QList<OneDimensionalCluster> oneDimensionalClusterList;
72     foreach (double coordinate, oneDimensionalCoordinateList)
73     {
74         QList<double> initialList;
75         initialList.append(coordinate);
76         OneDimensionalCluster cluster(initialList);
77         oneDimensionalClusterList.append(initialList);
78     }
79 
80     return oneDimensionalClusterList;
81 }
82 
reduceOneDimensionalClusterList(const QList<OneDimensionalCluster> & unreducedClusterList,double maximumDistance)83 QList<OneDimensionalCluster> OneDimensionalCluster::reduceOneDimensionalClusterList(const QList<OneDimensionalCluster> & unreducedClusterList, double maximumDistance)
84 {
85     if (unreducedClusterList.size() < 2)
86         return unreducedClusterList;
87 
88 
89     QList<OneDimensionalCluster> workingList(unreducedClusterList);
90     QList<OneDimensionalCluster> reducedList;
91     while (true)
92     {
93         Utils::sort(workingList);
94         reducedList.clear();
95         bool clusterMerged = false;
96 
97         for (int i = 0, n = workingList.size(); i != n; ) {
98 
99             OneDimensionalCluster currentCluster = workingList.at(i);
100             if (i + 1 < n) {
101                 OneDimensionalCluster nextCluster = workingList.at(i + 1);
102                 if ((nextCluster.mean() - currentCluster.mean()) < maximumDistance)
103                 {
104                     reducedList.append(currentCluster + nextCluster);
105                     ++i;
106                     clusterMerged = true;
107                 }
108                 else
109                 {
110                     reducedList.append(currentCluster);
111                 }
112             }
113             else
114             {
115                 reducedList.append(currentCluster);
116                 break;
117             }
118 
119         }
120 
121         workingList = reducedList;
122 
123         if (clusterMerged == false)
124             break;
125     }
126 
127 
128     return reducedList;
129 }
130 
reduceLines(const QList<double> & oneDimensionalCoordinateList,double maximumDistance)131 QList<double> OneDimensionalCluster::reduceLines(const QList<double> & oneDimensionalCoordinateList, double maximumDistance)
132 {
133     QList<OneDimensionalCluster>  clusterList(createOneDimensionalClusterList(oneDimensionalCoordinateList));
134     clusterList = reduceOneDimensionalClusterList(clusterList, maximumDistance);
135 
136     QList<double> lineList;
137     foreach (const OneDimensionalCluster &cluster, clusterList)
138         lineList.append(cluster.constFirst());
139 
140     return lineList;
141 }
142 
143 }
144