bool PointLayout::update(Dimension::Detail dd, const std::string& name) { if (m_finalized) { throw pdal_error("Can't update layout after points have been added."); } Dimension::DetailList detail; bool used = Utils::contains(m_used, dd.id()); for (auto id : m_used) { if (id == dd.id()) detail.push_back(dd); else detail.push_back(m_detail[id]); } if (!used) detail.push_back(dd); // Find the dimension in the list that we're referring to with // this update. auto di = std::find_if(detail.begin(), detail.end(), [dd](const Dimension::Detail& td) { return td.id() == dd.id(); }); Dimension::Detail *cur = &(*di); { auto sorter = [this](const Dimension::Detail& d1, const Dimension::Detail& d2) -> bool { if (d1.size() > d2.size()) return true; if (d1.size() < d2.size()) return false; return d1.id() < d2.id(); }; int offset = 0; std::sort(detail.begin(), detail.end(), sorter); for (auto& d : detail) { d.setOffset(offset); offset += (int)d.size(); } //NOTE - I tried forcing all points to be aligned on 8-byte boundaries // in case this would matter to the optimized memcpy, but it made // no difference. No sense wasting space for no difference. m_pointSize = (size_t)offset; } if (!used) m_used.push_back(dd.id()); for (auto& dtemp : detail) m_detail[dtemp.id()] = dtemp; return true; }
bool compare(Dimension::Id::Enum dim, PointId id1, PointId id2) { Dimension::Detail *dd = m_context.dimDetail(dim); switch (dd->type()) { case Dimension::Type::Float: return compare<float>(dim, id1, id2); break; case Dimension::Type::Double: return compare<double>(dim, id1, id2); break; case Dimension::Type::Signed8: return compare<int8_t>(dim, id1, id2); break; case Dimension::Type::Signed16: return compare<int16_t>(dim, id1, id2); break; case Dimension::Type::Signed32: return compare<int32_t>(dim, id1, id2); break; case Dimension::Type::Signed64: return compare<int64_t>(dim, id1, id2); break; case Dimension::Type::Unsigned8: return compare<uint8_t>(dim, id1, id2); break; case Dimension::Type::Unsigned16: return compare<uint16_t>(dim, id1, id2); break; case Dimension::Type::Unsigned32: return compare<uint32_t>(dim, id1, id2); break; case Dimension::Type::Unsigned64: return compare<uint64_t>(dim, id1, id2); break; case Dimension::Type::None: default: return false; break; } }
Dimension::Id::Enum PointLayout::assignDim(const std::string& name, Dimension::Type::Enum type) { Dimension::Id::Enum id = (Dimension::Id::Enum)m_nextFree; auto di = m_propIds.find(name); if (di != m_propIds.end()) id = di->second; Dimension::Detail dd = m_detail[id]; dd.setType(resolveType(type, dd.type())); if (update(dd, name)) { if (di == m_propIds.end()) { m_nextFree++; m_propIds[name] = id; } return id; } return Dimension::Id::Unknown; }
void BufferedInvocation::begin(PointBuffer& buffer) { PointContext ctx = buffer.m_context; Dimension::IdList const& dims = ctx.dims(); for (auto di = dims.begin(); di != dims.end(); ++di) { Dimension::Id::Enum d = *di; Dimension::Detail *dd = ctx.dimDetail(d); void *data = malloc(dd->size() * buffer.size()); m_buffers.push_back(data); // Hold pointer for deallocation char *p = (char *)data; for (PointId idx = 0; idx < buffer.size(); ++idx) { buffer.getFieldInternal(d, idx, (void *)p); p += dd->size(); } std::string name = ctx.dimName(*di); insertArgument(name, (uint8_t *)data, dd->type(), buffer.size()); } }
void BufferedInvocation::end(PointBuffer& buffer) { // for each entry in the script's outs dictionary, // look up that entry's name in the schema and then // copy the data into the right dimension spot in the // buffer std::vector<std::string> names; getOutputNames(names); PointContext ctx = buffer.m_context; Dimension::IdList const& dims = ctx.dims(); for (auto di = dims.begin(); di != dims.end(); ++di) { Dimension::Id::Enum d = *di; Dimension::Detail *dd = ctx.dimDetail(d); std::string name = ctx.dimName(*di); auto found = std::find(names.begin(), names.end(), name); if (found == names.end()) continue; // didn't have this dim in the names assert(name == *found); assert(hasOutputVariable(name)); size_t size = dd->size(); void *data = extractResult(name, dd->type()); char *p = (char *)data; for (PointId idx = 0; idx < buffer.size(); ++idx) { buffer.setField(d, dd->type(), idx, (void *)p); p += size; } } for (auto bi = m_buffers.begin(); bi != m_buffers.end(); ++bi) free(*bi); m_buffers.clear(); }
void PointLayout::registerDim(Dimension::Id::Enum id, Dimension::Type::Enum type) { Dimension::Detail dd = m_detail[id]; dd.setType(resolveType(type, dd.type())); update(dd, Dimension::name(id)); }
void PointBuffer::dump(std::ostream& ostr) const { using std::endl; const Dimension::IdList& dims = m_context.dims(); point_count_t numPoints = size(); ostr << "Contains " << numPoints << " points" << endl; for (PointId idx = 0; idx < numPoints; idx++) { ostr << "Point: " << idx << endl; for (auto di = dims.begin(); di != dims.end(); ++di) { Dimension::Id::Enum d = *di; Dimension::Detail *dd = m_context.dimDetail(d); ostr << Dimension::name(d) << " (" << Dimension::interpretationName(dd->type()) << ") : "; switch (dd->type()) { case Dimension::Type::Signed8: { ostr << (int)(getFieldInternal<int8_t>(d, idx)); break; } case Dimension::Type::Signed16: { ostr << getFieldInternal<int16_t>(d, idx); break; } case Dimension::Type::Signed32: { ostr << getFieldInternal<int32_t>(d, idx); break; } case Dimension::Type::Signed64: { ostr << getFieldInternal<int64_t>(d, idx); break; } case Dimension::Type::Unsigned8: { ostr << (unsigned)(getFieldInternal<uint8_t>(d, idx)); break; } case Dimension::Type::Unsigned16: { ostr << getFieldInternal<uint16_t>(d, idx); break; } case Dimension::Type::Unsigned32: { ostr << getFieldInternal<uint32_t>(d, idx); break; } case Dimension::Type::Unsigned64: { ostr << getFieldInternal<uint64_t>(d, idx); break; } case Dimension::Type::Float: { ostr << getFieldInternal<float>(d, idx); break; } case Dimension::Type::Double: { ostr << getFieldInternal<double>(d, idx); break; } default: throw; } ostr << endl; } } }