///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2021 Equinor ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RimMultipleLocations.h" #include "cafPdmUiDoubleValueEditor.h" #include "cafPdmUiListEditor.h" #include CAF_PDM_SOURCE_INIT( RimMultipleLocations, "RimMultipleLocations" ); namespace caf { template <> void AppEnum::setUp() { addItem( RimMultipleLocations::LocationType::COUNT, "COUNT", "Start/End/Number" ); addItem( RimMultipleLocations::LocationType::SPACING, "SPACING", "Start/End/Spacing" ); addItem( RimMultipleLocations::LocationType::CUSTOM, "CUSTOM", "User Specification" ); setDefault( RimMultipleLocations::LocationType::COUNT ); } } // namespace caf //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimMultipleLocations::RimMultipleLocations() { CAF_PDM_InitObject( "RimMultipleLocations", ":/FishBoneGroup16x16.png", "", "" ); CAF_PDM_InitField( &m_locationType, "LocationMode", caf::AppEnum( LocationType::COUNT ), "Location Defined By", "", "", "" ); CAF_PDM_InitField( &m_rangeStart, "RangeStart", 100.0, "Start MD", "", "", "" ); m_rangeStart.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() ); CAF_PDM_InitField( &m_rangeEnd, "RangeEnd", 250.0, "End MD", "", "", "" ); m_rangeEnd.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() ); CAF_PDM_InitFieldNoDefault( &m_rangeSpacing, "Spacing", "Spacing", "", "", "" ); m_rangeSpacing.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() ); CAF_PDM_InitField( &m_rangeCount, "RangeValveCount", 10, "Number of Items", "", "", "" ); CAF_PDM_InitFieldNoDefault( &m_locations, "Locations", "Measured Depths", "", "", "" ); m_locations.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimMultipleLocations::setRange( double minimumMD, double maximumMD ) { m_rangeStart = minimumMD; m_rangeEnd = maximumMD; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimMultipleLocations::updateRangesAndLocations() { double existingRangeStart = m_rangeStart(); double existingRangeEnd = m_rangeEnd(); if ( existingRangeStart != m_rangeStart() || existingRangeEnd != m_rangeEnd() ) { computeRangesAndLocations(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimMultipleLocations::measuredDepth( size_t valveIndex ) const { return m_locations()[valveIndex]; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimMultipleLocations::rangeStart() const { return m_rangeStart; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimMultipleLocations::rangeEnd() const { return m_rangeEnd; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const std::vector& RimMultipleLocations::locations() const { return m_locations(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimMultipleLocations::setLocationType( LocationType locationType ) { m_locationType = locationType; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimMultipleLocations::computeRangesAndLocations() { if ( m_locationType == LocationType::COUNT ) { int divisor = 1; if ( m_rangeCount > 2 ) divisor = m_rangeCount - 1; m_rangeSpacing = std::abs( m_rangeStart - m_rangeEnd ) / divisor; if ( m_rangeSpacing < minimumSpacingMeters() ) { m_rangeSpacing = minimumSpacingMeters(); m_rangeCount = rangeCountFromSpacing(); } } else if ( m_locationType == LocationType::SPACING ) { m_rangeCount = rangeCountFromSpacing(); } if ( m_locationType == LocationType::COUNT || m_locationType == LocationType::SPACING ) { std::vector validMeasuredDepths; for ( auto md : locationsFromStartSpacingAndCount( m_rangeStart(), m_rangeSpacing, m_rangeCount ) ) { validMeasuredDepths.push_back( md ); } m_locations = validMeasuredDepths; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimMultipleLocations::initFields( LocationType locationType, double rangeStart, double rangeEnd, double valveSpacing, int valveCount, const std::vector& locationOfValves ) { if ( locationType != LocationType::UNDEFINED ) { m_locationType = locationType; } if ( rangeStart != std::numeric_limits::infinity() ) { m_rangeStart = rangeStart; } if ( rangeEnd != std::numeric_limits::infinity() ) { m_rangeEnd = rangeEnd; } if ( valveSpacing != std::numeric_limits::infinity() ) { m_rangeSpacing = valveSpacing; } if ( valveCount != -1 ) { m_rangeCount = valveCount; } if ( !locationOfValves.empty() ) { m_locations = locationOfValves; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimMultipleLocations::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { { m_locations.uiCapability()->setUiName( "Measured Depths" ); m_rangeStart.uiCapability()->setUiName( "Start MD" ); m_rangeEnd.uiCapability()->setUiName( "End MD" ); m_rangeSpacing.uiCapability()->setUiName( "Spacing" ); } { uiOrdering.add( &m_locationType ); if ( m_locationType() != LocationType::CUSTOM ) { uiOrdering.add( &m_rangeStart ); uiOrdering.add( &m_rangeEnd ); if ( m_locationType() == LocationType::COUNT ) { uiOrdering.add( &m_rangeCount ); uiOrdering.add( &m_rangeSpacing ); } else if ( m_locationType() == LocationType::SPACING ) { uiOrdering.add( &m_rangeSpacing ); uiOrdering.add( &m_rangeCount ); } } uiOrdering.add( &m_locations ); } if ( m_locationType() == LocationType::CUSTOM ) { m_locations.uiCapability()->setUiReadOnly( false ); m_rangeSpacing.uiCapability()->setUiReadOnly( true ); m_rangeCount.uiCapability()->setUiReadOnly( true ); m_rangeStart.uiCapability()->setUiReadOnly( true ); m_rangeEnd.uiCapability()->setUiReadOnly( true ); } else { m_locations.uiCapability()->setUiReadOnly( true ); m_rangeSpacing.uiCapability()->setUiReadOnly( false ); m_rangeCount.uiCapability()->setUiReadOnly( false ); m_rangeStart.uiCapability()->setUiReadOnly( false ); m_rangeEnd.uiCapability()->setUiReadOnly( false ); if ( m_locationType() == LocationType::COUNT ) { m_rangeSpacing.uiCapability()->setUiReadOnly( true ); m_rangeCount.uiCapability()->setUiReadOnly( false ); } else { m_rangeSpacing.uiCapability()->setUiReadOnly( false ); m_rangeCount.uiCapability()->setUiReadOnly( true ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimMultipleLocations::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) { bool recomputeLocations = false; if ( changedField == &m_locationType ) { if ( m_locationType == LocationType::COUNT || m_locationType == LocationType::SPACING ) { recomputeLocations = true; } } if ( changedField == &m_rangeStart || changedField == &m_rangeEnd || changedField == &m_rangeCount || changedField == &m_rangeSpacing ) { recomputeLocations = true; } if ( changedField == &m_rangeSpacing ) { double minimumDistanceMeter = minimumSpacingMeters(); m_rangeSpacing = std::clamp( m_rangeSpacing(), minimumDistanceMeter, std::max( m_rangeSpacing(), minimumDistanceMeter ) ); } if ( recomputeLocations ) { computeRangesAndLocations(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- int RimMultipleLocations::rangeCountFromSpacing() const { int rangeCount = ( std::fabs( m_rangeStart - m_rangeEnd ) / m_rangeSpacing ) + 1; if ( rangeCount < 1 ) { rangeCount = 1; } return rangeCount; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimMultipleLocations::minimumSpacingMeters() const { // Minimum distance between fishbones is 13.0m // Use 10.0m to allow for some flexibility return 10.0; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimMultipleLocations::locationsFromStartSpacingAndCount( double start, double spacing, size_t count ) { std::vector measuredDepths; for ( size_t i = 0; i < count; i++ ) { measuredDepths.push_back( start + spacing * i ); } return measuredDepths; }