diff --git a/src/Mod/PartDesign/App/FeatureHole.cpp b/src/Mod/PartDesign/App/FeatureHole.cpp index 9c014d291f..884ce8a5ca 100644 --- a/src/Mod/PartDesign/App/FeatureHole.cpp +++ b/src/Mod/PartDesign/App/FeatureHole.cpp @@ -71,7 +71,8 @@ namespace PartDesign { const char* Hole::DepthTypeEnums[] = { "Dimension", "ThroughAll", /*, "UpToFirst", */ NULL }; const char* Hole::ThreadTypeEnums[] = { "None", "ISOMetricProfile", "ISOMetricFineProfile", "UNC", "UNF", "UNEF", NULL}; -const char* Hole::ThreadFitEnums[] = { "Standard", "Close", "Wide", NULL}; +const char* Hole::ClearanceMetricEnums[] = { "Standard", "Close", "Wide", NULL}; +const char* Hole::ClearanceUTSEnums[] = { "Normal", "Close", "Loose", NULL }; const char* Hole::DrillPointEnums[] = { "Flat", "Angled", NULL}; /* "None" profile */ @@ -449,6 +450,39 @@ const double Hole::metricHoleDiameters[36][4] = { 68.0, 70.0, 77.0, 78.0} }; +const Hole::UTSClearanceDefinition Hole::UTSHoleDiameters[22] = +{ + /* UTS clearance hole diameters according to ASME B18.2.8 */ + // for information: the norm defines a drill bit number (that is in turn standardized in another ASME norm). + // as result the norm defines a minimal clearance which is the diameter of that drill bit. + // we use here this minimal clearance as the theoretical exact hole diameter as this is also done in the ISO norm. + // {screw class, close, normal, loose} + { "#0", 1.7, 1.9, 2.4 }, + { "#1", 2.1, 2.3, 2.6 }, + { "#2", 2.4, 2.6, 2.9 }, + { "#3", 2.7, 2.9, 3.3 }, + { "#4", 3.0, 3.3, 3.7 }, + { "#5", 3.6, 4.0, 4.4 }, + { "#6", 3.9, 4.3, 4.7 }, + { "#8", 4.6, 5.0, 5.4 }, + { "#10", 5.2, 5.6, 6.0 }, + // "#12" not defined + { "1/4", 6.8, 7.1, 7.5 }, + { "5/16", 8.3, 8.7, 9.1 }, + { "3/8", 9.9, 10.3, 10.7 }, + { "7/16", 11.5, 11.9, 12.3 }, + { "1/2", 13.5, 14.3, 15.5 }, + // "9/16" not defined + { "5/8", 16.7, 17.5, 18.6 }, + { "3/4", 19.8, 20.6, 23.0 }, + { "7/8", 23.0, 23.8, 26.2 }, + { "1", 26.2, 27.8, 29.4 }, + { "1 1/8", 29.4, 31.0, 33.3 }, + { "1 1/4", 32.5, 34.1, 36.5 }, + { "1 3/8", 36.5, 38.1, 40.9 }, + { "1 1/2", 39.7, 41.3, 44.0 } +}; + /* ISO coarse metric enums */ std::vector Hole::HoleCutType_ISOmetric_Enums = { "None", "Counterbore", "Countersink", "Cheesehead (deprecated)", "Countersink socket screw (deprecated)", "Cap screw (deprecated)" }; const char* Hole::ThreadSize_ISOmetric_Enums[] = { "M1", "M1.1", "M1.2", "M1.4", "M1.6", @@ -566,8 +600,8 @@ Hole::Hole() ADD_PROPERTY_TYPE(ThreadClass, (0L), "Hole", App::Prop_None, "Thread class"); ThreadClass.setEnums(ThreadClass_None_Enums); - ADD_PROPERTY_TYPE(ThreadFit, (0L), "Hole", App::Prop_None, "Thread fit"); - ThreadFit.setEnums(ThreadFitEnums); + ADD_PROPERTY_TYPE(ThreadFit, (0L), "Hole", App::Prop_None, "Clearance hole fit"); + ThreadFit.setEnums(ClearanceMetricEnums); ADD_PROPERTY_TYPE(Diameter, (6.0), "Hole", App::Prop_None, "Diameter"); @@ -812,52 +846,130 @@ void Hole::updateDiameterParam() } else { // we have a clearance hole bool found = false; - int MatrixRowSize = sizeof(metricHoleDiameters) / sizeof(metricHoleDiameters[0]); - switch ( ThreadFit.getValue() ) { - case 0: /* standard fit */ - // read diameter out of matrix - for (int i = 0; i < MatrixRowSize; i++) { - if (metricHoleDiameters[i][0] == diameter) { - diameter = metricHoleDiameters[i][2]; - found = true; - break; + std::string threadType = ThreadType.getValueAsString(); + // UTS and metric have a different clearance hole set + if (threadType == "ISOMetricProfile" || threadType == "ISOMetricFineProfile") { + int MatrixRowSizeMetric = sizeof(metricHoleDiameters) / sizeof(metricHoleDiameters[0]); + switch (ThreadFit.getValue()) { + case 0: /* standard fit */ + // read diameter out of matrix + for (int i = 0; i < MatrixRowSizeMetric; i++) { + if (metricHoleDiameters[i][0] == diameter) { + diameter = metricHoleDiameters[i][2]; + found = true; + break; + } } - } - // if nothing was found (e.g. if not metric), we must calculate - if (!found) { - diameter = (5 * ((int)((diameter * 110) / 5))) / 100.0; - } - break; - case 1: /* close fit */ - // read diameter out of matrix - for (int i = 0; i < MatrixRowSize; i++) { - if (metricHoleDiameters[i][0] == diameter) { - diameter = metricHoleDiameters[i][1]; - found = true; - break; + // if nothing is defined (e.g. for M2.2, M9 and M11), we must calculate + // we use the factors defined for M5 in the metricHoleDiameters list + if (!found) { + diameter = diameter * 1.10; } - } - // if nothing was found, we must calculate - if (!found) { - diameter = (5 * ((int)((diameter * 105) / 5))) / 100.0; - } - break; - case 2: /* wide fit */ - // read diameter out of matrix - for (int i = 0; i < MatrixRowSize; i++) { - if (metricHoleDiameters[i][0] == diameter) { - diameter = metricHoleDiameters[i][3]; - found = true; - break; + break; + case 1: /* close fit */ + // read diameter out of matrix + for (int i = 0; i < MatrixRowSizeMetric; i++) { + if (metricHoleDiameters[i][0] == diameter) { + diameter = metricHoleDiameters[i][1]; + found = true; + break; + } } + // if nothing was found, we must calculate + if (!found) { + diameter = diameter * 1.06; + } + break; + case 2: /* wide fit */ + // read diameter out of matrix + for (int i = 0; i < MatrixRowSizeMetric; i++) { + if (metricHoleDiameters[i][0] == diameter) { + diameter = metricHoleDiameters[i][3]; + found = true; + break; + } + } + // if nothing was found, we must calculate + if (!found) { + diameter = diameter * 1.16; + } + break; + default: + throw Base::IndexError("Thread fit out of range"); } - // if nothing was found, we must calculate - if (!found) { - diameter = (5 * ((int)((diameter * 115) / 5))) / 100.0; + } + else if (threadType == "UNC" || threadType == "UNF" || threadType == "UNEF") { + std::string ThreadSizeString = ThreadSize.getValueAsString(); + int MatrixRowSizeUTS = sizeof(UTSHoleDiameters) / sizeof(UTSHoleDiameters[0]); + switch (ThreadFit.getValue()) { + case 0: /* normal fit */ + // read diameter out of matrix + for (int i = 0; i < MatrixRowSizeUTS; i++) { + if (UTSHoleDiameters[i].designation == ThreadSizeString) { + diameter = UTSHoleDiameters[i].normal; + found = true; + break; + } + } + // if nothing was found (if "#12" or "9/16"), we must calculate + // // we use the factors defined for "3/8" in the UTSHoleDiameters list + if (!found) { + diameter = diameter * 1.08; + } + break; + case 1: /* close fit */ + // read diameter out of matrix + for (int i = 0; i < MatrixRowSizeUTS; i++) { + if (UTSHoleDiameters[i].designation == ThreadSizeString) { + diameter = UTSHoleDiameters[i].close; + found = true; + break; + } + } + // if nothing was found, we must calculate + if (!found) { + diameter = diameter * 1.04; + } + break; + case 2: /* loose fit */ + // read diameter out of matrix + for (int i = 0; i < MatrixRowSizeUTS; i++) { + if (UTSHoleDiameters[i].designation == ThreadSizeString) { + diameter = UTSHoleDiameters[i].loose; + found = true; + break; + } + } + // if nothing was found, we must calculate + if (!found) { + diameter = diameter * 1.12; + } + break; + default: + throw Base::IndexError("Thread fit out of range"); + } + } + else { + switch (ThreadFit.getValue()) { + case 0: /* normal fit */ + // we must calculate + if (!found) { + diameter = diameter * 1.1; + } + break; + case 1: /* close fit */ + if (!found) { + diameter = diameter * 1.05; + } + break; + case 2: /* loose fit */ + if (!found) { + diameter = diameter * 1.15; + } + break; + default: + throw Base::IndexError("Thread fit out of range"); } - break; - default: - assert( 0 ); } } Diameter.setValue(diameter); @@ -887,6 +999,7 @@ void Hole::onChanged(const App::Property *prop) ThreadSize.setEnums(ThreadSize_ISOmetric_Enums); ThreadClass.setEnums(ThreadClass_ISOmetric_Enums); HoleCutType.setEnums(HoleCutType_ISOmetric_Enums); + ThreadFit.setEnums(ClearanceMetricEnums); Threaded.setReadOnly(false); ThreadSize.setReadOnly(false); // thread class and direction are only sensible if threaded @@ -899,6 +1012,7 @@ void Hole::onChanged(const App::Property *prop) ThreadSize.setEnums(ThreadSize_ISOmetricfine_Enums); ThreadClass.setEnums(ThreadClass_ISOmetricfine_Enums); HoleCutType.setEnums(HoleCutType_ISOmetricfine_Enums); + ThreadFit.setEnums(ClearanceMetricEnums); Threaded.setReadOnly(false); ThreadSize.setReadOnly(false); // thread class and direction are only sensible if threaded @@ -911,6 +1025,7 @@ void Hole::onChanged(const App::Property *prop) ThreadSize.setEnums(ThreadSize_UNC_Enums); ThreadClass.setEnums(ThreadClass_UNC_Enums); HoleCutType.setEnums(HoleCutType_UNC_Enums); + ThreadFit.setEnums(ClearanceUTSEnums); Threaded.setReadOnly(false); ThreadSize.setReadOnly(false); // thread class and direction are only sensible if threaded @@ -923,6 +1038,7 @@ void Hole::onChanged(const App::Property *prop) ThreadSize.setEnums(ThreadSize_UNF_Enums); ThreadClass.setEnums(ThreadClass_UNF_Enums); HoleCutType.setEnums(HoleCutType_UNF_Enums); + ThreadFit.setEnums(ClearanceUTSEnums); Threaded.setReadOnly(false); ThreadSize.setReadOnly(false); // thread class and direction are only sensible if threaded @@ -935,6 +1051,7 @@ void Hole::onChanged(const App::Property *prop) ThreadSize.setEnums(ThreadSize_UNEF_Enums); ThreadClass.setEnums(ThreadClass_UNEF_Enums); HoleCutType.setEnums(HoleCutType_UNEF_Enums); + ThreadFit.setEnums(ClearanceUTSEnums); Threaded.setReadOnly(false); ThreadSize.setReadOnly(false); // thread class and direction are only sensible if threaded diff --git a/src/Mod/PartDesign/App/FeatureHole.h b/src/Mod/PartDesign/App/FeatureHole.h index 72cf07fc13..9ec22ccd3f 100644 --- a/src/Mod/PartDesign/App/FeatureHole.h +++ b/src/Mod/PartDesign/App/FeatureHole.h @@ -90,6 +90,14 @@ public: static const double metricHoleDiameters[36][4]; + typedef struct { + std::string designation; + double close; + double normal; + double loose; + } UTSClearanceDefinition; + static const UTSClearanceDefinition UTSHoleDiameters[22]; + virtual void Restore(Base::XMLReader & reader); virtual void updateProps(); @@ -99,7 +107,8 @@ protected: private: static const char* DepthTypeEnums[]; static const char* ThreadTypeEnums[]; - static const char* ThreadFitEnums[]; + static const char* ClearanceMetricEnums[]; + static const char* ClearanceUTSEnums[]; static const char* DrillPointEnums[]; static const char* ThreadDirectionEnums[]; diff --git a/src/Mod/PartDesign/Gui/TaskHoleParameters.cpp b/src/Mod/PartDesign/Gui/TaskHoleParameters.cpp index 8e281f7dcf..fd35108360 100644 --- a/src/Mod/PartDesign/Gui/TaskHoleParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskHoleParameters.cpp @@ -440,31 +440,37 @@ void TaskHoleParameters::threadTypeChanged(int index) // now set the new type, this will reset the comboboxes to item 0 pcHole->ThreadType.setValue(index); - // Size - // the size for ISO type has either the form "M3x0.35" or just "M3" - // so we need to check if the size contains a 'x'. If yes, check if the string - // up to the 'x' is exists in the new list + // size and clearance if (TypeClass == QByteArray("ISO")) { + // the size for ISO type has either the form "M3x0.35" or just "M3" + // so we need to check if the size contains a 'x'. If yes, check if the string + // up to the 'x' is exists in the new list if (ThreadSizeString.indexOf(QString::fromLatin1("x")) > -1) { // we have an ISO fine size // cut of the part behind the 'x' ThreadSizeString = ThreadSizeString.left(ThreadSizeString.indexOf(QString::fromLatin1("x"))); } - // search if the string exists in the combobox int threadSizeIndex = ui->ThreadSize->findText(ThreadSizeString, Qt::MatchContains); if (threadSizeIndex > -1) { // we can set it ui->ThreadSize->setCurrentIndex(threadSizeIndex); } - } - - // for the UTS types the entries are the same - if (TypeClass == QByteArray("UTS")) { + // the names of the clearance types are different in ISO and UTS + ui->ThreadFit->setItemText(0, QCoreApplication::translate("TaskHoleParameters", "Standard", nullptr)); + ui->ThreadFit->setItemText(1, QCoreApplication::translate("TaskHoleParameters", "Close", nullptr)); + ui->ThreadFit->setItemText(2, QCoreApplication::translate("TaskHoleParameters", "Wide", nullptr)); + } + else if (TypeClass == QByteArray("UTS")) { + // for all UTS types the size entries are the same int threadSizeIndex = ui->ThreadSize->findText(ThreadSizeString, Qt::MatchContains); if (threadSizeIndex > -1) { ui->ThreadSize->setCurrentIndex(threadSizeIndex); } + // the names of the clearance types are different in ISO and UTS + ui->ThreadFit->setItemText(0, QCoreApplication::translate("TaskHoleParameters", "Normal", nullptr)); + ui->ThreadFit->setItemText(1, QCoreApplication::translate("TaskHoleParameters", "Close", nullptr)); + ui->ThreadFit->setItemText(2, QCoreApplication::translate("TaskHoleParameters", "Loose", nullptr)); } // Class and cut type @@ -475,6 +481,8 @@ void TaskHoleParameters::threadTypeChanged(int index) int holeCutIndex = ui->HoleCutType->findText(CutTypeString, Qt::MatchContains); if (holeCutIndex > -1) ui->HoleCutType->setCurrentIndex(holeCutIndex); + + recomputeFeature(); } void TaskHoleParameters::threadSizeChanged(int index)