MCPcopy Create free account
hub / github.com/PDAL/PDAL / filter

Method filter

filters/LloydKMeansFilter.cpp:92–163  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

90}
91
92void LloydKMeansFilter::filter(PointView& view)
93{
94 if (!view.size() || (view.size() < m_k))
95 return;
96
97 // come up with k random samples for initial cluster centers (based on
98 // spatial farthest point sampling)
99 PointIdList ids = Segmentation::farthestPointSampling(view, m_k);
100
101 // setup table with at least XYZ as required by KDIndex, plus any
102 // additional dimensions as specified via filter options
103 ColumnPointTable table;
104 table.layout()->registerDims({Id::X, Id::Y, Id::Z});
105 table.layout()->registerDims(m_dimIdList);
106 table.finalize();
107
108 // create view of initial cluster centers
109 PointViewPtr centers(new PointView(table));
110 PointId i(0);
111 for (auto const& id : ids)
112 {
113 centers->setField(Id::X, i, view.getFieldAs<double>(Id::X, id));
114 centers->setField(Id::Y, i, view.getFieldAs<double>(Id::Y, id));
115 centers->setField(Id::Z, i, view.getFieldAs<double>(Id::Z, id));
116 for (auto const& dimid : m_dimIdList)
117 {
118 centers->setField(dimid, i, view.getFieldAs<double>(dimid, id));
119 }
120 i++;
121 }
122
123 // construct KDFlexIndex for nearest neighbor search
124 KDFlexIndex kdi(*centers, m_dimIdList);
125 kdi.build();
126
127 // update cluster centers through specified number of iterations
128 for (int iter = 0; iter < m_maxiters; ++iter)
129 {
130 // initialize mean and count for each cluster
131 std::vector<std::vector<double>> M1(m_dimIdList.size(),
132 std::vector<double>(m_k, 0.0));
133 std::vector<point_count_t> cnt(m_k, 0);
134
135 // for every point, find closest cluster center and assign ClusterID
136 for (PointRef p : view)
137 {
138 PointId q = kdi.neighbor(p);
139 p.setField(Id::ClusterID, q);
140
141 // update cluster size and mean
142 cnt[q]++;
143 point_count_t n(cnt[q]);
144 for (size_t i = 0; i < m_dimIdList.size(); ++i)
145 {
146 double delta = p.getFieldAs<double>(m_dimIdList[i]) - M1[i][q];
147 double delta_n = delta / n;
148 M1[i][q] += delta_n;
149 }

Callers

nothing calls this directly

Calls 8

farthestPointSamplingFunction · 0.85
registerDimsMethod · 0.80
neighborMethod · 0.80
invalidateProductsMethod · 0.80
sizeMethod · 0.45
finalizeMethod · 0.45
setFieldMethod · 0.45
buildMethod · 0.45

Tested by

no test coverage detected