2020-09-28 15:38:32 +02:00
|
|
|
/************************************************************************
|
|
|
|
**
|
|
|
|
** @file vdimensions.cpp
|
|
|
|
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
|
|
|
** @date 25 9, 2020
|
|
|
|
**
|
|
|
|
** @brief
|
|
|
|
** @copyright
|
|
|
|
** This source code is part of the Valentina project, a pattern making
|
|
|
|
** program, whose allow create and modeling patterns of clothing.
|
|
|
|
** Copyright (C) 2020 Valentina project
|
|
|
|
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
|
|
|
|
**
|
|
|
|
** Valentina 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.
|
|
|
|
**
|
|
|
|
** Valentina 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 for more details.
|
|
|
|
**
|
|
|
|
** You should have received a copy of the GNU General Public License
|
|
|
|
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
**
|
|
|
|
*************************************************************************/
|
|
|
|
#include "vdimensions.h"
|
|
|
|
|
|
|
|
#include <QSet>
|
|
|
|
#include <QVector>
|
2021-01-18 19:43:53 +01:00
|
|
|
#include <cmath>
|
2020-09-28 15:38:32 +02:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
VAbstartMeasurementDimension::VAbstartMeasurementDimension(Unit units)
|
|
|
|
: m_units(units)
|
|
|
|
{}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
VAbstartMeasurementDimension::VAbstartMeasurementDimension(Unit units, qreal min, qreal max, qreal step)
|
2020-09-28 15:38:32 +02:00
|
|
|
: m_units(units),
|
|
|
|
m_minValue(min),
|
|
|
|
m_maxValue(max),
|
|
|
|
m_step(step)
|
|
|
|
{}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
auto VAbstartMeasurementDimension::IsValid() -> bool
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
|
|
|
m_error.clear();
|
|
|
|
return IsUnitsValid() && IsRangeValid() && IsStepValid() && IsBaseValid();
|
|
|
|
}
|
|
|
|
|
2022-02-14 12:26:24 +01:00
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
auto VAbstartMeasurementDimension::RangeMin() const -> int
|
|
|
|
{
|
|
|
|
if (m_circumference)
|
|
|
|
{
|
|
|
|
const int rangeMinCm = 20;
|
|
|
|
const int rangeMinMm = 200;
|
|
|
|
const int rangeMinInch = 8;
|
|
|
|
|
|
|
|
switch(Units())
|
|
|
|
{
|
|
|
|
case Unit::Cm:
|
|
|
|
return rangeMinCm;
|
|
|
|
case Unit::Mm:
|
|
|
|
return rangeMinMm;
|
|
|
|
case Unit::Inch:
|
|
|
|
return rangeMinInch;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
auto VAbstartMeasurementDimension::RangeMax() const -> int
|
|
|
|
{
|
|
|
|
if (m_circumference)
|
|
|
|
{
|
|
|
|
const int rangeMaxCm = 272;
|
|
|
|
const int rangeMaxMm = 2720;
|
|
|
|
const int rangeMaxInch = 107;
|
|
|
|
|
|
|
|
switch(Units())
|
|
|
|
{
|
|
|
|
case Unit::Cm:
|
|
|
|
return rangeMaxCm;
|
|
|
|
case Unit::Mm:
|
|
|
|
return rangeMaxMm;
|
|
|
|
case Unit::Inch:
|
|
|
|
return rangeMaxInch;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
auto VAbstartMeasurementDimension::Name() const -> QString
|
|
|
|
{
|
|
|
|
return m_customName.isEmpty() ? DimensionName(Type()) : m_customName;
|
|
|
|
}
|
|
|
|
|
2020-09-28 15:38:32 +02:00
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
auto VAbstartMeasurementDimension::ValidSteps() const -> QVector<qreal>
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
2021-01-18 19:43:53 +01:00
|
|
|
const qreal stepBarrier = 8.5;
|
|
|
|
const qreal s = 0.5;
|
2020-09-28 15:38:32 +02:00
|
|
|
|
2021-01-18 19:43:53 +01:00
|
|
|
QVector<qreal> steps;
|
|
|
|
steps.reserve(qRound((stepBarrier - s) * 2 - 1));
|
|
|
|
|
|
|
|
const qreal diff = m_maxValue - m_minValue;
|
|
|
|
if (qFuzzyIsNull(diff))
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
|
|
|
steps.append(0); // only one possible value
|
|
|
|
}
|
|
|
|
else if (diff > 0)
|
|
|
|
{
|
2021-01-18 19:43:53 +01:00
|
|
|
qreal candidate = 1;
|
|
|
|
do
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
2021-01-18 19:43:53 +01:00
|
|
|
const qreal step = (m_units == Unit::Mm ? candidate * 10 : candidate);
|
|
|
|
qreal intpart;
|
|
|
|
if (qFuzzyIsNull(std::modf(diff / step, &intpart)))
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
|
|
|
steps.append(step);
|
|
|
|
}
|
2021-01-18 19:43:53 +01:00
|
|
|
candidate += s;
|
2020-09-28 15:38:32 +02:00
|
|
|
}
|
2021-01-18 19:43:53 +01:00
|
|
|
while(candidate < stepBarrier);
|
2020-09-28 15:38:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return steps;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
auto VAbstartMeasurementDimension::ValidBases() const -> QVector<qreal>
|
2020-10-07 16:12:53 +02:00
|
|
|
{
|
2021-01-19 20:13:17 +01:00
|
|
|
return VAbstartMeasurementDimension::ValidBases(m_minValue, m_maxValue, m_step, QSet<qreal>());
|
2020-10-07 16:12:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
auto VAbstartMeasurementDimension::ValidBasesList() const -> QStringList
|
2020-10-07 16:12:53 +02:00
|
|
|
{
|
2021-01-18 19:43:53 +01:00
|
|
|
QVector<qreal> bases = ValidBases();
|
2020-10-07 16:12:53 +02:00
|
|
|
QStringList list;
|
2021-01-18 19:43:53 +01:00
|
|
|
list.reserve(bases.size());
|
2020-10-07 16:12:53 +02:00
|
|
|
for(auto &base : bases)
|
|
|
|
{
|
|
|
|
list.append(QString::number(base));
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-19 20:13:17 +01:00
|
|
|
auto VAbstartMeasurementDimension::ValidBases(qreal min, qreal max, qreal step,
|
|
|
|
const QSet<qreal> &exclude) -> QVector<qreal>
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
2021-01-18 19:43:53 +01:00
|
|
|
QVector<qreal> validBases;
|
2020-09-28 15:38:32 +02:00
|
|
|
|
2021-01-18 19:43:53 +01:00
|
|
|
if (step < 0 || min > max)
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
|
|
|
return validBases;
|
|
|
|
}
|
2021-01-18 19:43:53 +01:00
|
|
|
|
|
|
|
if (qFuzzyIsNull(step))
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
|
|
|
step = 1;
|
|
|
|
}
|
|
|
|
|
2021-01-18 19:43:53 +01:00
|
|
|
validBases.reserve(qRound((max - min) / step));
|
|
|
|
|
|
|
|
qreal value = min;
|
|
|
|
do
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
2021-01-19 20:13:17 +01:00
|
|
|
if (not exclude.contains(value))
|
|
|
|
{
|
|
|
|
validBases.append(value);
|
|
|
|
}
|
2021-01-18 19:43:53 +01:00
|
|
|
value += step;
|
2020-09-28 15:38:32 +02:00
|
|
|
}
|
2021-01-18 19:43:53 +01:00
|
|
|
while(value < max + step);
|
2020-09-28 15:38:32 +02:00
|
|
|
|
2021-01-19 20:13:17 +01:00
|
|
|
if (validBases.isEmpty())
|
|
|
|
{
|
|
|
|
value = min;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
validBases.append(value);
|
|
|
|
value += step;
|
|
|
|
}
|
|
|
|
while(value < max + step);
|
|
|
|
}
|
|
|
|
|
2020-09-28 15:38:32 +02:00
|
|
|
return validBases;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
auto VAbstartMeasurementDimension::IsRangeValid() -> bool
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
|
|
|
bool valid = m_minValue > 0 && m_maxValue > 0 && m_minValue >= RangeMin() && m_minValue <= RangeMax()
|
|
|
|
&& m_minValue <= m_maxValue;
|
|
|
|
|
|
|
|
if (not valid)
|
|
|
|
{
|
|
|
|
m_error = tr("Invalid min/max range");
|
|
|
|
}
|
|
|
|
|
|
|
|
return valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
auto VAbstartMeasurementDimension::IsStepValid() -> bool
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
|
|
|
bool valid = ValidSteps().indexOf(m_step) != -1;
|
|
|
|
if (not valid)
|
|
|
|
{
|
|
|
|
m_error = tr("Invalid step");
|
|
|
|
}
|
|
|
|
|
|
|
|
return valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
auto VAbstartMeasurementDimension::IsBaseValid() -> bool
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
|
|
|
bool valid = ValidBases().indexOf(m_baseValue) != -1;
|
|
|
|
if (not valid)
|
|
|
|
{
|
|
|
|
m_error = tr("Base value invalid");
|
|
|
|
}
|
|
|
|
|
|
|
|
return valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
auto VAbstartMeasurementDimension::IsUnitsValid() const -> bool
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
|
|
|
return m_units == Unit::Cm || m_units == Unit::Mm || m_units == Unit::Inch;
|
|
|
|
}
|
|
|
|
|
2020-10-06 17:00:53 +02:00
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
auto VAbstartMeasurementDimension::DimensionName(MeasurementDimension type) -> QString
|
2020-10-06 17:00:53 +02:00
|
|
|
{
|
|
|
|
switch(type)
|
|
|
|
{
|
2020-10-15 08:35:08 +02:00
|
|
|
case MeasurementDimension::X:
|
2020-10-20 15:29:11 +02:00
|
|
|
return tr("Height", "dimension");
|
2020-10-15 08:35:08 +02:00
|
|
|
case MeasurementDimension::Y:
|
2020-10-20 15:29:11 +02:00
|
|
|
return tr("Size", "dimension");
|
2020-10-15 08:35:08 +02:00
|
|
|
case MeasurementDimension::W:
|
2020-10-20 15:29:11 +02:00
|
|
|
return tr("Waist", "dimension");
|
2020-10-15 08:35:08 +02:00
|
|
|
case MeasurementDimension::Z:
|
2020-10-20 15:29:11 +02:00
|
|
|
return tr("Hip", "dimension");
|
2020-10-15 08:35:08 +02:00
|
|
|
default:
|
2022-02-14 12:26:24 +01:00
|
|
|
return {};
|
2020-10-06 17:00:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2022-02-14 12:26:24 +01:00
|
|
|
auto VAbstartMeasurementDimension::DimensionToolTip(const MeasurementDimension_p &dimension, bool fc) -> QString
|
2020-10-06 17:00:53 +02:00
|
|
|
{
|
2022-02-14 12:26:24 +01:00
|
|
|
if (dimension.isNull())
|
2020-10-06 17:00:53 +02:00
|
|
|
{
|
2022-02-14 12:26:24 +01:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(dimension->Type())
|
|
|
|
{
|
|
|
|
case MeasurementDimension::Y:
|
|
|
|
if (dimension->CustomName().isEmpty() && dimension->IsCircumference())
|
|
|
|
{
|
|
|
|
return fc ? tr("Chest full circumference", "dimension") : tr("Chest half circumference", "dimension");
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
case MeasurementDimension::W:
|
|
|
|
if (dimension->CustomName().isEmpty() && dimension->IsCircumference())
|
|
|
|
{
|
|
|
|
return fc ? tr("Waist full circumference", "dimension") : tr("Waist half circumference", "dimension");
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
case MeasurementDimension::Z:
|
|
|
|
if (dimension->CustomName().isEmpty() && dimension->IsCircumference())
|
|
|
|
{
|
|
|
|
return fc ? tr("Hip full circumference", "dimension") : tr("Hip half circumference", "dimension");
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
case MeasurementDimension::X:
|
|
|
|
default:
|
|
|
|
return {};
|
2020-10-06 17:00:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-28 15:38:32 +02:00
|
|
|
// VXMeasurementDimension
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
VXMeasurementDimension::VXMeasurementDimension(Unit units)
|
|
|
|
: VAbstartMeasurementDimension(units)
|
|
|
|
{}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
VXMeasurementDimension::VXMeasurementDimension(Unit units, qreal min, qreal max, qreal step)
|
2020-09-28 15:38:32 +02:00
|
|
|
: VAbstartMeasurementDimension(units, min, max, step)
|
|
|
|
{}
|
|
|
|
|
|
|
|
// VYMeasurementDimension
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
VYMeasurementDimension::VYMeasurementDimension(Unit units)
|
|
|
|
: VAbstartMeasurementDimension(units)
|
|
|
|
{}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
VYMeasurementDimension::VYMeasurementDimension(Unit units, qreal min, qreal max, qreal step)
|
2020-09-28 15:38:32 +02:00
|
|
|
: VAbstartMeasurementDimension(units, min, max, step)
|
|
|
|
{}
|
|
|
|
|
|
|
|
// VWMeasurementDimension
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
VWMeasurementDimension::VWMeasurementDimension(Unit units)
|
|
|
|
: VAbstartMeasurementDimension(units)
|
|
|
|
{}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
VWMeasurementDimension::VWMeasurementDimension(Unit units, qreal min, qreal max, qreal step)
|
2020-09-28 15:38:32 +02:00
|
|
|
: VAbstartMeasurementDimension(units, min, max, step)
|
|
|
|
{}
|
|
|
|
|
|
|
|
// VZMeasurementDimension
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
VZMeasurementDimension::VZMeasurementDimension(Unit units)
|
|
|
|
: VAbstartMeasurementDimension(units)
|
|
|
|
{}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-01-18 19:43:53 +01:00
|
|
|
VZMeasurementDimension::VZMeasurementDimension(Unit units, qreal min, qreal max, qreal step)
|
2020-09-28 15:38:32 +02:00
|
|
|
: VAbstartMeasurementDimension(units, min, max, step)
|
|
|
|
{}
|
|
|
|
|
2022-02-14 12:26:24 +01:00
|
|
|
// VDimensionRestriction
|
2020-09-28 15:38:32 +02:00
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2022-02-14 12:26:24 +01:00
|
|
|
VDimensionRestriction::VDimensionRestriction(qreal min, qreal max, const QString &exclude) :
|
|
|
|
m_min(min),
|
|
|
|
m_max(max)
|
2020-09-28 15:38:32 +02:00
|
|
|
{
|
2022-02-14 12:26:24 +01:00
|
|
|
SetExcludeString(exclude);
|
2020-09-28 15:38:32 +02:00
|
|
|
}
|
2021-01-19 20:13:17 +01:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
void VDimensionRestriction::SetExcludeString(const QString &exclude)
|
|
|
|
{
|
|
|
|
m_exclude.clear();
|
|
|
|
|
|
|
|
QStringList values = exclude.split(';');
|
|
|
|
for(auto &value : values)
|
|
|
|
{
|
|
|
|
bool ok = false;
|
|
|
|
qreal val = value.toDouble(&ok);
|
|
|
|
|
|
|
|
if (ok)
|
|
|
|
{
|
|
|
|
m_exclude.insert(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
auto VDimensionRestriction::GetExcludeString() const -> QString
|
|
|
|
{
|
|
|
|
QList<qreal> list = m_exclude.values();
|
|
|
|
QStringList excludeList;
|
|
|
|
|
|
|
|
for(auto &value : list)
|
|
|
|
{
|
|
|
|
excludeList.append(QString::number(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
return excludeList.join(';');
|
|
|
|
}
|