Loading files
76de63d66This file is pinned to the selected release. Download the original to open it in your design tool.
/*
* LibrePCB - Professional EDA for everyone!
* Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
* https://librepcb.org/
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*******************************************************************************
* Includes
******************************************************************************/
#include "boarddesignrules.h"
#include <QtCore>
/*******************************************************************************
* Namespace
******************************************************************************/
namespace librepcb {
/*******************************************************************************
* Constructors / Destructor
******************************************************************************/
BoardDesignRules::BoardDesignRules() noexcept
: // general attributes
mName(tr("LibrePCB Default Design Rules")),
mDescription(),
// stop mask
mStopMaskClearanceRatio(Ratio::percent0()), // 0%
mStopMaskClearanceMin(100000), // 0.1mm
mStopMaskClearanceMax(100000), // 0.1mm
mStopMaskMaxViaDrillDiameter(500000), // 0.5mm
// cream mask
mCreamMaskClearanceRatio(Ratio::percent100() / 10), // 10%
mCreamMaskClearanceMin(0), // 0.0mm
mCreamMaskClearanceMax(1000000), // 1.0mm
// restring
mRestringPadRatio(Ratio::percent100() / 4), // 25%
mRestringPadMin(250000), // 0.25mm
mRestringPadMax(2000000), // 2.0mm
mRestringViaRatio(Ratio::percent100() / 4), // 25%
mRestringViaMin(200000), // 0.2mm
mRestringViaMax(2000000) // 2.0mm
{
}
BoardDesignRules::BoardDesignRules(const BoardDesignRules& other)
: BoardDesignRules() {
*this = other;
}
BoardDesignRules::BoardDesignRules(const SExpression& node,
const Version& fileFormat)
: BoardDesignRules() // this loads all default values!
{
// general attributes
mName = deserialize<ElementName>(node.getChild("name/@0"), fileFormat);
mDescription = node.getChild("description/@0").getValue();
// stop mask
if (const SExpression* e = node.tryGetChild("stopmask_clearance_ratio")) {
mStopMaskClearanceRatio =
deserialize<UnsignedRatio>(e->getChild("@0"), fileFormat);
}
if (const SExpression* e = node.tryGetChild("stopmask_clearance_min")) {
mStopMaskClearanceMin =
deserialize<UnsignedLength>(e->getChild("@0"), fileFormat);
}
if (const SExpression* e = node.tryGetChild("stopmask_clearance_max")) {
mStopMaskClearanceMax =
deserialize<UnsignedLength>(e->getChild("@0"), fileFormat);
}
if (const SExpression* e =
node.tryGetChild("stopmask_max_via_drill_diameter")) {
mStopMaskMaxViaDrillDiameter =
deserialize<UnsignedLength>(e->getChild("@0"), fileFormat);
}
// cream mask
if (const SExpression* e = node.tryGetChild("creammask_clearance_ratio")) {
mCreamMaskClearanceRatio =
deserialize<UnsignedRatio>(e->getChild("@0"), fileFormat);
}
if (const SExpression* e = node.tryGetChild("creammask_clearance_min")) {
mCreamMaskClearanceMin =
deserialize<UnsignedLength>(e->getChild("@0"), fileFormat);
}
if (const SExpression* e = node.tryGetChild("creammask_clearance_max")) {
mCreamMaskClearanceMax =
deserialize<UnsignedLength>(e->getChild("@0"), fileFormat);
}
// restring
if (const SExpression* e = node.tryGetChild("restring_pad_ratio")) {
mRestringPadRatio =
deserialize<UnsignedRatio>(e->getChild("@0"), fileFormat);
}
if (const SExpression* e = node.tryGetChild("restring_pad_min")) {
mRestringPadMin =
deserialize<UnsignedLength>(e->getChild("@0"), fileFormat);
}
if (const SExpression* e = node.tryGetChild("restring_pad_max")) {
mRestringPadMax =
deserialize<UnsignedLength>(e->getChild("@0"), fileFormat);
}
if (const SExpression* e = node.tryGetChild("restring_via_ratio")) {
mRestringViaRatio =
deserialize<UnsignedRatio>(e->getChild("@0"), fileFormat);
}
if (const SExpression* e = node.tryGetChild("restring_via_min")) {
mRestringViaMin =
deserialize<UnsignedLength>(e->getChild("@0"), fileFormat);
}
if (const SExpression* e = node.tryGetChild("restring_via_max")) {
mRestringViaMax =
deserialize<UnsignedLength>(e->getChild("@0"), fileFormat);
}
// force validating properties, throw exception on error
try {
setStopMaskClearanceBounds(mStopMaskClearanceMin, mStopMaskClearanceMax);
setCreamMaskClearanceBounds(mCreamMaskClearanceMin, mCreamMaskClearanceMax);
setRestringPadBounds(mRestringPadMin, mRestringPadMax);
setRestringViaBounds(mRestringViaMin, mRestringViaMax);
} catch (const Exception& e) {
throw RuntimeError(__FILE__, __LINE__,
tr("Invalid design rules: %1").arg(e.getMsg()));
}
}
BoardDesignRules::~BoardDesignRules() noexcept {
}
/*******************************************************************************
* Setters
******************************************************************************/
void BoardDesignRules::setStopMaskClearanceBounds(const UnsignedLength& min,
const UnsignedLength& max) {
if (max >= min) {
mStopMaskClearanceMin = min;
mStopMaskClearanceMax = max;
} else {
throw RuntimeError(__FILE__, __LINE__,
tr("Stop mask clearance: MAX must be >= MIN"));
}
}
void BoardDesignRules::setCreamMaskClearanceBounds(const UnsignedLength& min,
const UnsignedLength& max) {
if (max >= min) {
mCreamMaskClearanceMin = min;
mCreamMaskClearanceMax = max;
} else {
throw RuntimeError(__FILE__, __LINE__,
tr("Cream mask clearance: MAX must be >= MIN"));
}
}
void BoardDesignRules::setRestringPadBounds(const UnsignedLength& min,
const UnsignedLength& max) {
if (max >= min) {
mRestringPadMin = min;
mRestringPadMax = max;
} else {
throw RuntimeError(__FILE__, __LINE__,
tr("Restring pads: MAX must be >= MIN"));
}
}
void BoardDesignRules::setRestringViaBounds(const UnsignedLength& min,
const UnsignedLength& max) {
if (max >= min) {
mRestringViaMin = min;
mRestringViaMax = max;
} else {
throw RuntimeError(__FILE__, __LINE__,
tr("Restring vias: MAX must be >= MIN"));
}
}
/*******************************************************************************
* General Methods
******************************************************************************/
void BoardDesignRules::restoreDefaults() noexcept {
*this = BoardDesignRules();
}
void BoardDesignRules::serialize(SExpression& root) const {
// general attributes
root.ensureLineBreak();
root.appendChild("name", mName);
root.ensureLineBreak();
root.appendChild("description", mDescription);
root.ensureLineBreak();
// stop mask
root.appendChild("stopmask_clearance_ratio", mStopMaskClearanceRatio);
root.ensureLineBreak();
root.appendChild("stopmask_clearance_min", mStopMaskClearanceMin);
root.ensureLineBreak();
root.appendChild("stopmask_clearance_max", mStopMaskClearanceMax);
root.ensureLineBreak();
root.appendChild("stopmask_max_via_drill_diameter",
mStopMaskMaxViaDrillDiameter);
root.ensureLineBreak();
// cream mask
root.appendChild("creammask_clearance_ratio", mCreamMaskClearanceRatio);
root.ensureLineBreak();
root.appendChild("creammask_clearance_min", mCreamMaskClearanceMin);
root.ensureLineBreak();
root.appendChild("creammask_clearance_max", mCreamMaskClearanceMax);
root.ensureLineBreak();
// restring
root.appendChild("restring_pad_ratio", mRestringPadRatio);
root.ensureLineBreak();
root.appendChild("restring_pad_min", mRestringPadMin);
root.ensureLineBreak();
root.appendChild("restring_pad_max", mRestringPadMax);
root.ensureLineBreak();
root.appendChild("restring_via_ratio", mRestringViaRatio);
root.ensureLineBreak();
root.appendChild("restring_via_min", mRestringViaMin);
root.ensureLineBreak();
root.appendChild("restring_via_max", mRestringViaMax);
root.ensureLineBreak();
}
/*******************************************************************************
* Helper Methods
******************************************************************************/
bool BoardDesignRules::doesViaRequireStopMask(const Length& drillDia) const
noexcept {
return (drillDia > *mStopMaskMaxViaDrillDiameter ? true : false);
}
UnsignedLength BoardDesignRules::calcStopMaskClearance(
const Length& padSize) const noexcept {
return UnsignedLength(
qBound(*mStopMaskClearanceMin,
padSize.scaled(mStopMaskClearanceRatio->toNormalized()),
*mStopMaskClearanceMax));
}
UnsignedLength BoardDesignRules::calcCreamMaskClearance(
const Length& padSize) const noexcept {
return UnsignedLength(
qBound(*mCreamMaskClearanceMin,
padSize.scaled(mCreamMaskClearanceRatio->toNormalized()),
*mCreamMaskClearanceMax));
}
UnsignedLength BoardDesignRules::calcPadRestring(const Length& drillDia) const
noexcept {
return UnsignedLength(qBound(
*mRestringPadMin, drillDia.scaled(mRestringPadRatio->toNormalized()),
*mRestringPadMax));
}
UnsignedLength BoardDesignRules::calcViaRestring(const Length& drillDia) const
noexcept {
return UnsignedLength(qBound(
*mRestringViaMin, drillDia.scaled(mRestringViaRatio->toNormalized()),
*mRestringViaMax));
}
/*******************************************************************************
* Operator Overloadings
******************************************************************************/
BoardDesignRules& BoardDesignRules::operator=(
const BoardDesignRules& rhs) noexcept {
// general attributes
mName = rhs.mName;
mDescription = rhs.mDescription;
// stop mask
mStopMaskClearanceRatio = rhs.mStopMaskClearanceRatio;
mStopMaskClearanceMin = rhs.mStopMaskClearanceMin;
mStopMaskClearanceMax = rhs.mStopMaskClearanceMax;
mStopMaskMaxViaDrillDiameter = rhs.mStopMaskMaxViaDrillDiameter;
// cream mask
mCreamMaskClearanceRatio = rhs.mCreamMaskClearanceRatio;
mCreamMaskClearanceMin = rhs.mCreamMaskClearanceMin;
mCreamMaskClearanceMax = rhs.mCreamMaskClearanceMax;
// restring
mRestringPadRatio = rhs.mRestringPadRatio;
mRestringPadMin = rhs.mRestringPadMin;
mRestringPadMax = rhs.mRestringPadMax;
mRestringViaRatio = rhs.mRestringViaRatio;
mRestringViaMin = rhs.mRestringViaMin;
mRestringViaMax = rhs.mRestringViaMax;
return *this;
}
/*******************************************************************************
* End of File
******************************************************************************/
} // namespace librepcb