Import: DXF backend/frontend, report more unsupported features info
Now for unsupported features we report on line numbers and on the entity handle, in case that unsupported feature is a DXF entity. To avoid flooding the output, only a maximum of 5 instances are reported with details. The rest simply add up to the global count and are ellipsized in the report. Report output is now in sentence case.
This commit is contained in:
@@ -4228,38 +4228,38 @@ class DxfImportReporter:
|
||||
Formats the statistics into a human-readable string for console output.
|
||||
"""
|
||||
if not self.stats:
|
||||
return "DXF Import: No statistics were returned from the importer.\n"
|
||||
return "DXF Import: no statistics were returned from the importer.\n"
|
||||
|
||||
lines = ["\n--- DXF Import Summary ---"]
|
||||
lines = ["\n--- DXF import summary ---"]
|
||||
|
||||
# General info
|
||||
lines.append(f"DXF Version: {self.stats.get('dxfVersion', 'Unknown')}")
|
||||
lines.append(f"File Encoding: {self.stats.get('dxfEncoding', 'Unknown')}")
|
||||
lines.append(f"DXF version: {self.stats.get('dxfVersion', 'Unknown')}")
|
||||
lines.append(f"File encoding: {self.stats.get('dxfEncoding', 'Unknown')}")
|
||||
|
||||
# Scaling info
|
||||
file_units = self.stats.get('fileUnits', 'Not specified')
|
||||
source = self.stats.get('scalingSource', '')
|
||||
if source:
|
||||
lines.append(f"File Units: {file_units} (from {source})")
|
||||
lines.append(f"File units: {file_units} (from {source})")
|
||||
else:
|
||||
lines.append(f"File Units: {file_units}")
|
||||
lines.append(f"File units: {file_units}")
|
||||
|
||||
manual_scaling = self.stats.get('importSettings', {}).get('Manual scaling factor', '1.0')
|
||||
lines.append(f"Manual Scaling Factor: {manual_scaling}")
|
||||
lines.append(f"Manual scaling factor: {manual_scaling}")
|
||||
|
||||
final_scaling = self.stats.get('finalScalingFactor', 1.0)
|
||||
lines.append(f"Final Scaling: 1 DXF unit = {final_scaling:.4f} mm")
|
||||
lines.append(f"Final scaling: 1 DXF unit = {final_scaling:.4f} mm")
|
||||
lines.append("")
|
||||
|
||||
# Timing
|
||||
lines.append("Performance:")
|
||||
cpp_time = self.stats.get('importTimeSeconds', 0.0)
|
||||
lines.append(f" - C++ Import Time: {cpp_time:.4f} seconds")
|
||||
lines.append(f" - Total Import Time: {self.total_time:.4f} seconds")
|
||||
lines.append(f" - C++ import time: {cpp_time:.4f} seconds")
|
||||
lines.append(f" - Total import time: {self.total_time:.4f} seconds")
|
||||
lines.append("")
|
||||
|
||||
# Settings
|
||||
lines.append("Import Settings:")
|
||||
lines.append("Import settings:")
|
||||
settings = self.stats.get('importSettings', {})
|
||||
if settings:
|
||||
for key, value in sorted(settings.items()):
|
||||
@@ -4269,7 +4269,7 @@ class DxfImportReporter:
|
||||
lines.append("")
|
||||
|
||||
# Counts
|
||||
lines.append("Entity Counts:")
|
||||
lines.append("Entity counts:")
|
||||
total_read = 0
|
||||
entities = self.stats.get('entityCounts', {})
|
||||
if entities:
|
||||
@@ -4283,15 +4283,31 @@ class DxfImportReporter:
|
||||
lines.append(f"FreeCAD objects created: {self.stats.get('totalEntitiesCreated', 0)}")
|
||||
lines.append("")
|
||||
|
||||
lines.append("Unsupported Features:")
|
||||
lines.append("Import issues and unsupported features:")
|
||||
unsupported = self.stats.get('unsupportedFeatures', {})
|
||||
if unsupported:
|
||||
for key, value in sorted(unsupported.items()):
|
||||
lines.append(f" - {key}: {value} time(s)")
|
||||
else:
|
||||
lines.append(" (None)")
|
||||
for key, occurrences in sorted(unsupported.items()):
|
||||
count = len(occurrences)
|
||||
max_details_to_show = 5
|
||||
|
||||
lines.append("--- End of Summary ---\n")
|
||||
details_list = []
|
||||
for i, (line, handle) in enumerate(occurrences):
|
||||
if i >= max_details_to_show:
|
||||
break
|
||||
if handle:
|
||||
details_list.append(f"line {line} (handle {handle})")
|
||||
else:
|
||||
details_list.append(f"line {line} (no handle available)")
|
||||
|
||||
details_str = ", ".join(details_list)
|
||||
if count > max_details_to_show:
|
||||
lines.append(f" - {key}: {count} time(s). Examples: {details_str}, ...")
|
||||
else:
|
||||
lines.append(f" - {key}: {count} time(s) at {details_str}")
|
||||
else:
|
||||
lines.append(" (none)")
|
||||
|
||||
lines.append("--- End of summary ---\n")
|
||||
return "\n".join(lines)
|
||||
|
||||
def report_to_console(self):
|
||||
|
||||
@@ -1404,7 +1404,14 @@ Py::Object ImpExpDxfRead::getStatsAsPyObject()
|
||||
// Create a nested dictionary for any unsupported DXF features encountered.
|
||||
Py::Dict unsupportedFeaturesDict;
|
||||
for (const auto& pair : m_stats.unsupportedFeatures) {
|
||||
unsupportedFeaturesDict.setItem(pair.first.c_str(), Py::Long(pair.second));
|
||||
Py::List occurrencesList;
|
||||
for (const auto& occurrence : pair.second) {
|
||||
Py::Tuple infoTuple(2);
|
||||
infoTuple.setItem(0, Py::Long(occurrence.first));
|
||||
infoTuple.setItem(1, Py::String(occurrence.second));
|
||||
occurrencesList.append(infoTuple);
|
||||
}
|
||||
unsupportedFeaturesDict.setItem(pair.first.c_str(), occurrencesList);
|
||||
}
|
||||
statsDict.setItem("unsupportedFeatures", unsupportedFeaturesDict);
|
||||
|
||||
|
||||
@@ -2342,8 +2342,8 @@ bool CDxfRead::ReadDimension()
|
||||
|
||||
bool CDxfRead::ReadUnknownEntity()
|
||||
{
|
||||
UnsupportedFeature("Entity type '%s'", m_record_data);
|
||||
ProcessAllEntityAttributes();
|
||||
UnsupportedFeature("Entity type '%s'", m_record_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2403,7 +2403,7 @@ void CDxfRead::UnsupportedFeature(const char* format, args&&... argValuess)
|
||||
{
|
||||
// NOLINTNEXTLINE(runtime/printf)
|
||||
std::string formattedMessage = fmt::sprintf(format, std::forward<args>(argValuess)...);
|
||||
m_stats.unsupportedFeatures[formattedMessage]++;
|
||||
m_stats.unsupportedFeatures[formattedMessage].emplace_back(m_line, m_current_entity_handle);
|
||||
}
|
||||
|
||||
bool CDxfRead::get_next_record()
|
||||
@@ -2798,6 +2798,8 @@ bool CDxfRead::ReadEntity()
|
||||
{
|
||||
InitializeAttributes();
|
||||
m_entityAttributes.SetDefaults();
|
||||
m_current_entity_handle.clear();
|
||||
SetupStringAttribute(eHandle, m_current_entity_handle);
|
||||
EntityNormalVector.Set(0, 0, 1);
|
||||
Setup3DVectorAttribute(eExtrusionDirection, EntityNormalVector);
|
||||
SetupStringAttribute(eLinetypeName, m_entityAttributes.m_LineType);
|
||||
|
||||
@@ -187,7 +187,7 @@ struct DxfImportStats
|
||||
double finalScalingFactor = 1.0;
|
||||
std::map<std::string, int> entityCounts;
|
||||
std::map<std::string, std::string> importSettings;
|
||||
std::map<std::string, int> unsupportedFeatures;
|
||||
std::map<std::string, std::vector<std::pair<int, std::string>>> unsupportedFeatures;
|
||||
int totalEntitiesCreated = 0;
|
||||
};
|
||||
|
||||
@@ -200,6 +200,7 @@ enum eDXFGroupCode_t
|
||||
ePrimaryText = 1,
|
||||
eName = 2,
|
||||
eExtraText = 3,
|
||||
eHandle = 5,
|
||||
eLinetypeName = 6,
|
||||
eTextStyleName = 7,
|
||||
eLayerName = 8,
|
||||
@@ -462,6 +463,7 @@ private:
|
||||
bool m_not_eof = true;
|
||||
int m_line = 0;
|
||||
bool m_repeat_last_record = false;
|
||||
std::string m_current_entity_handle;
|
||||
|
||||
// The scaling from DXF units to millimetres.
|
||||
// This does not include the dxfScaling option
|
||||
|
||||
Reference in New Issue
Block a user