diff --git a/Artifacts/clientdist/clientpackage.zip b/Artifacts/clientdist/clientpackage.zip index 287203dd..2e84b006 100644 Binary files a/Artifacts/clientdist/clientpackage.zip and b/Artifacts/clientdist/clientpackage.zip differ diff --git a/Artifacts/clientdist/clientsourcepackage.zip b/Artifacts/clientdist/clientsourcepackage.zip index c400fceb..527edf65 100644 Binary files a/Artifacts/clientdist/clientsourcepackage.zip and b/Artifacts/clientdist/clientsourcepackage.zip differ diff --git a/Client/src/common/AMCImplementation_LayerView.js b/Client/src/common/AMCImplementation_LayerView.js index 8653ef5e..b0a392bf 100644 --- a/Client/src/common/AMCImplementation_LayerView.js +++ b/Client/src/common/AMCImplementation_LayerView.js @@ -326,6 +326,28 @@ class LayerViewImpl { } + computeChannelColumnRange (pointsChannelName, pointsColumnName) + { + if (this[pointsChannelName] && this[pointsChannelName][pointsColumnName]) { + let dataArray = this[pointsChannelName][pointsColumnName]; + + let maxValue = Number.NEGATIVE_INFINITY; + let minValue = Number.POSITIVE_INFINITY; + + for (let i = 0; i < dataArray.length; i++) { + let value = dataArray[i]; + if (value > maxValue) { + maxValue = value; + } + if (value < minValue) { + minValue = value; + } + } + this[pointsChannelName][pointsColumnName].max = maxValue; + this[pointsChannelName][pointsColumnName].min = minValue; + } + } + makeLaserOnColors () { this.laserOnPointsColorArray = null; @@ -351,6 +373,37 @@ class LayerViewImpl { } + makeLaserPowerColors () + { + this.layerPointsColorArray = null; + + if (this.laser && this.laser.power && this.layerPointsArray) { + const powerRange = (this.laser.power.max - this.laser.power.min); + if (powerRange > 0) { + + let pointCount = this.laser.power.length; + let colors = []; + + for (let pointIndex = 0; pointIndex < pointCount; pointIndex++) { + let power = this.laser.power[pointIndex]; + let fraction = (power - this.laser.power.min) / powerRange; + if (fraction >= 0.0) { + if (fraction > 1.0) + fraction = 1.0; + } else { + fraction = 0.0; + } + + const hue = (fraction) * 240 / 360; + colors.push (this.hslToRgb (hue, 1.0, 0.5)); + } + + this.layerPointsColorArray = colors; + } + } + } + + hslToRgb(h, s, l) { // Ensure h, s, l are in the range [0, 1] h = h % 1; // Wrap around if h is greater than 1 @@ -429,6 +482,8 @@ class LayerViewImpl { // Assign the data array to the corresponding column this[pointsChannelName][pointsColumnName] = pointsChannelDataArray; + + this.computeChannelColumnRange (pointsChannelName, pointsColumnName); } clearPoints () @@ -469,6 +524,10 @@ class LayerViewImpl { if (this.layerPointsMode == "laseron") { this.makeLaserOnColors (); } + + if (this.layerPointsMode == "powerramp") { + this.makeLaserPowerColors (); + } } setColorMode (newColorMode) { @@ -587,6 +646,16 @@ class LayerViewImpl { } + getPointPower (pointIndex) + { + if (this.laser && this.laser.power) { + if (pointIndex >= 0 && pointIndex < this.laser.power.length) { + return this.laser.power[pointIndex]; + } + } + return null; + } + updateLoadedLayer () { if (!this.glInstance) return; diff --git a/Client/src/modules/AMCModule_LayerView.vue b/Client/src/modules/AMCModule_LayerView.vue index 7ebdc34f..8fafcae3 100644 --- a/Client/src/modules/AMCModule_LayerView.vue +++ b/Client/src/modules/AMCModule_LayerView.vue @@ -157,8 +157,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. this.LayerViewerInstance.setColorMode ("laseron"); } else if (this.LayerViewerInstance.layerPointsMode == "laseron") { + this.LayerViewerInstance.setColorMode ("powerramp"); + } + else if (this.LayerViewerInstance.layerPointsMode == "powerramp") { this.LayerViewerInstance.setColorMode ("uniform"); - } else { + } + else { this.LayerViewerInstance.setColorMode ("time"); } }, @@ -240,6 +244,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return "Color: LaserOn"; } + if (this.LayerViewerInstance.layerPointsMode == "powerramp") { + return "Color: Power"; + } + return "Color: Uniform"; }, @@ -357,6 +365,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } else { console.log(`${key}: ${floatArray.length}`); } + } else if (key.toLowerCase() === 'power') { + if (this.LayerViewerInstance) { + this.LayerViewerInstance.loadPointsChannelData ("laser", key.toLowerCase(), floatArray); + } else { + console.log(`${key}: ${floatArray.length}`); + } } } else { console.warn(`Key "${key}" is not an array and will be ignored.`); @@ -588,6 +602,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. let pointVelocity = this.LayerViewerInstance.getPointVelocity (pointIndex); let pointAcceleration = this.LayerViewerInstance.getPointAcceleration (pointIndex); let pointJerk = this.LayerViewerInstance.getPointJerk (pointIndex); + let pointPower = this.LayerViewerInstance.getPointPower (pointIndex); let infoCaption = `Point ID = ${pointIndex.toFixed(0)}\n`; if (pointPosition) { @@ -605,7 +620,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. let jerkinmeterspersecondsquared = pointJerk.j / 1000000.0; infoCaption += `Jerk: ${jerkinmeterspersecondsquared.toFixed(4)} km/s³\n`; } - + if (pointPower) { + let powerinwatts = pointPower; // * 1000.0; + infoCaption += `Power: ${powerinwatts.toFixed(4)} W\n`; + } this.lastMouseX = mouseX; this.lastMouseY = mouseY; diff --git a/Drivers/ScanLabSMC/Implementation/libmcdriver_scanlabsmc_smcjobinstance.cpp b/Drivers/ScanLabSMC/Implementation/libmcdriver_scanlabsmc_smcjobinstance.cpp index 7e00b8e4..4a950a37 100644 --- a/Drivers/ScanLabSMC/Implementation/libmcdriver_scanlabsmc_smcjobinstance.cpp +++ b/Drivers/ScanLabSMC/Implementation/libmcdriver_scanlabsmc_smcjobinstance.cpp @@ -795,8 +795,10 @@ void CSMCJobInstance::ReadSimulationFile_SMC_v1_0(LibMCEnv::PDataTable pDataTabl {{CSMCCSVParser::FieldParserType::Double, CSMCCSVParser::FieldProcessingStep::Extend | CSMCCSVParser::FieldProcessingStep::Interpolate }, &scanheadY}, {{CSMCCSVParser::FieldParserType::LaserSignal,CSMCCSVParser::FieldProcessingStep::Nop}, &laserSignal}, {{CSMCCSVParser::FieldParserType::UInt32,CSMCCSVParser::FieldProcessingStep::Nop}, &laserToggle}, - {{CSMCCSVParser::FieldParserType::None,CSMCCSVParser::FieldProcessingStep::Nop}, nullptr}, - {{CSMCCSVParser::FieldParserType::None,CSMCCSVParser::FieldProcessingStep::Nop}, nullptr}, + //{{CSMCCSVParser::FieldParserType::None,CSMCCSVParser::FieldProcessingStep::Nop}, nullptr}, + //{{CSMCCSVParser::FieldParserType::None,CSMCCSVParser::FieldProcessingStep::Nop}, nullptr}, + {{CSMCCSVParser::FieldParserType::Double,CSMCCSVParser::FieldProcessingStep::Nop}, &activeChannel0}, + {{CSMCCSVParser::FieldParserType::Double,CSMCCSVParser::FieldProcessingStep::Nop}, &activeChannel1}, {{CSMCCSVParser::FieldParserType::Int,CSMCCSVParser::FieldProcessingStep::Nop}, &cmdCount}, {{CSMCCSVParser::FieldParserType::None,CSMCCSVParser::FieldProcessingStep::Nop}, nullptr}, {{CSMCCSVParser::FieldParserType::None,CSMCCSVParser::FieldProcessingStep::Nop}, nullptr}, @@ -815,8 +817,8 @@ void CSMCJobInstance::ReadSimulationFile_SMC_v1_0(LibMCEnv::PDataTable pDataTabl pDataTable->AddColumn("x", "X", LibMCEnv::eDataTableColumnType::DoubleColumn); pDataTable->AddColumn("y", "Y", LibMCEnv::eDataTableColumnType::DoubleColumn); pDataTable->AddColumn("laseron", "LaserOn", LibMCEnv::eDataTableColumnType::Uint32Column); + pDataTable->AddColumn("power", "Laser Power", LibMCEnv::eDataTableColumnType::DoubleColumn); pDataTable->AddColumn("active1", "Active Channel 1", LibMCEnv::eDataTableColumnType::DoubleColumn); - pDataTable->AddColumn("active2", "Active Channel 2", LibMCEnv::eDataTableColumnType::DoubleColumn); pDataTable->AddColumn("cmdindex", "Command Index", LibMCEnv::eDataTableColumnType::Int32Column); m_dJobDuration = (double)timestampValues.size() / (double)SCANLABSMC_MICROSTEPSPERSECOND; @@ -833,6 +835,12 @@ void CSMCJobInstance::ReadSimulationFile_SMC_v1_0(LibMCEnv::PDataTable pDataTabl pDataTable->SetUint32ColumnValues("laseron", laserSignal); laserSignal.resize(0); + + pDataTable->SetDoubleColumnValues("power", activeChannel0); + activeChannel0.resize(0); + + pDataTable->SetDoubleColumnValues("active1", activeChannel1); + activeChannel1.resize(0); } void CSMCJobInstance::ReadLogRecordFile(LibMCEnv::PDataTable pDataTable) diff --git a/Implementation/Core/amc_toolpathlayerdata.cpp b/Implementation/Core/amc_toolpathlayerdata.cpp index 754a6523..cf5b7c81 100644 --- a/Implementation/Core/amc_toolpathlayerdata.cpp +++ b/Implementation/Core/amc_toolpathlayerdata.cpp @@ -429,9 +429,11 @@ namespace AMC { } - +#if USEALLMODIFICATIONFACTORS for (uint32_t nFactorIndex = 0; nFactorIndex < 3; nFactorIndex++) { - +#else // USE ONLY FACTOR_F MODIFICATOR + for (uint32_t nFactorIndex = 0; nFactorIndex < 1; nFactorIndex++) { +#endif Lib3MF::eToolpathProfileModificationFactor factorType = Lib3MF::eToolpathProfileModificationFactor::Unknown; uint32_t factorFlag = 0; switch (nFactorIndex) { @@ -478,7 +480,8 @@ namespace AMC { Lib3MF::sHatchModificationInterpolationData* pSubInterpolationData = nullptr; if (nonLinearCounts.size() > 0) { nSubInterpolationCount = nonLinearCounts.at(nHatchIndex); - pSubInterpolationData = &m_InterpolationData.at(nInterpolationDataStartIndex + nTotalSubInterpolationCount); + if (nSubInterpolationCount > 0) + pSubInterpolationData = &m_InterpolationData.at(nInterpolationDataStartIndex + nTotalSubInterpolationCount); } pDstOverride->m_dFactors[nFactorIndex] = pSrcOverride->m_Point1Factor; diff --git a/Implementation/LibMCEnv/libmcenv_datatable.cpp b/Implementation/LibMCEnv/libmcenv_datatable.cpp index 8cb181b7..f3a1ecae 100644 --- a/Implementation/LibMCEnv/libmcenv_datatable.cpp +++ b/Implementation/LibMCEnv/libmcenv_datatable.cpp @@ -293,7 +293,33 @@ class CDataTableColumn_Double : public CDataTableColumn void fillScatterplotChannel(AMC::CScatterplot* pScatterplot, const std::string& sChannel, const std::string& sColumn, double dScaleFactor, double dOffset) override { - throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_NOTIMPLEMENTED); + if (pScatterplot == nullptr) + throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDPARAM); + + auto& channelEntries = pScatterplot->getChannelEntries(); + auto channelIter = channelEntries.find(sChannel); + + if (channelIter == channelEntries.end()) { + channelEntries[sChannel][sColumn] = std::vector(); + } + else { + auto& columnEntries = channelIter->second; + + if (columnEntries.find(sColumn) == columnEntries.end()) + columnEntries[sColumn] = std::vector(); + else { + std::string sException = "The channel = " + sChannel + " with the column = " + sColumn + " already exists"; + throw std::runtime_error(sException.c_str()); + } + } + + auto& vecColumn = channelEntries[sChannel][sColumn]; + + vecColumn.resize(m_Rows.size()); + + for (size_t nIndex = 0; nIndex < m_Rows.size(); nIndex++) { + vecColumn[nIndex] = (double)m_Rows.at(nIndex) * dScaleFactor + dOffset; + } } }; diff --git a/Implementation/LibMCEnv/libmcenv_toolpathlayer.cpp b/Implementation/LibMCEnv/libmcenv_toolpathlayer.cpp index fd6b095d..13a038df 100644 --- a/Implementation/LibMCEnv/libmcenv_toolpathlayer.cpp +++ b/Implementation/LibMCEnv/libmcenv_toolpathlayer.cpp @@ -559,7 +559,7 @@ void CToolpathLayer::EvaluateTypedHatchProfileInterpolation(const LibMCEnv_uint3 } else { if ((pCountArrayBuffer != nullptr) || (pEvaluationDataBuffer != nullptr)) { - throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_COULDNOTEVALUATEHATCHPROFILES); + //throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_COULDNOTEVALUATEHATCHPROFILES); } }