[TD]fix BrokenView dimensions

This commit is contained in:
wandererfan
2024-04-15 10:16:23 -04:00
committed by WandererFan
parent 4f4df89442
commit 41bce2eaf4
3 changed files with 232 additions and 104 deletions

View File

@@ -158,8 +158,8 @@ App::DocumentObjectExecReturn* DrawBrokenView::execute()
TopoDS_Shape brokenShape = breakShape(safeShape);
m_compressedShape = compressShape(brokenShape);
// BRepTools::Write(brokenShape, "DBVbroken.brep"); //debug
// BRepTools::Write(m_compressedShape, "DBVcompressed.brep");
BRepTools::Write(brokenShape, "DBVbroken.brep"); //debug
BRepTools::Write(m_compressedShape, "DBVcompressed.brep");
partExec(m_compressedShape);
@@ -850,27 +850,52 @@ BreakList DrawBrokenView::makeSortedBreakList(const std::vector<App::DocumentObj
//! find the compressed location of the breaks, and sort the result by lower limit
BreakList DrawBrokenView::makeSortedBreakListCompressed(const std::vector<App::DocumentObject*>& breaks, Base::Vector3d moveDirection, bool descend) const
{
// Base::Console().Message("DBV::makeSortedBreakListCompressed(%d, %s)\n", breaks.size(),
// DU::formatVector(moveDirection).c_str());
// sortedBreaks is in lowLimit order
auto sortedBreaks = makeSortedBreakList(breaks, moveDirection, descend);
BreakList result;
size_t iBreak{0};
for (auto& breakObj : sortedBreaks) {
BreakListEntry newEntry;
double breakSum{0};
for (size_t iSum = iBreak + 1; iSum < sortedBreaks.size(); iSum++) {
// shift right by the removed amount of all the breaks to the right of this break
breakSum += sortedBreaks.at(iSum).netRemoved;
if (isDirectionReversed(moveDirection)) {
// reversed X+ high low X-
// our list is sorted ascending by low limit - each is further left than the previous
// so we must reverse our list to get the correct shift values.
std::reverse(sortedBreaks.begin(), sortedBreaks.end());
for (size_t iSum = iBreak + 1; iSum < sortedBreaks.size(); iSum++) {
// shift right by the removed amount of all the breaks to the right of this break
breakSum += sortedBreaks.at(iSum).netRemoved;
}
newEntry.breakObj = breakObj.breakObj;
newEntry.lowLimit = breakObj.lowLimit - breakSum; // move to right
newEntry.highLimit = newEntry.lowLimit + Gap.getValue();
newEntry.netRemoved = breakObj.netRemoved;
result.push_back(newEntry);
} else {
// forward X- low high X+
for (size_t iSum = iBreak + 1; iSum < sortedBreaks.size(); iSum++) {
// shift right by the removed amount of all the breaks to the right of this break
breakSum += sortedBreaks.at(iSum).netRemoved;
}
newEntry.breakObj = breakObj.breakObj;
newEntry.lowLimit = breakObj.lowLimit + breakObj.netRemoved + breakSum;
newEntry.highLimit = newEntry.lowLimit + Gap.getValue();
newEntry.netRemoved = breakObj.netRemoved;
result.push_back(newEntry);
}
newEntry.breakObj = breakObj.breakObj;
newEntry.lowLimit = breakObj.lowLimit + breakObj.netRemoved + breakSum;
newEntry.highLimit = newEntry.lowLimit + Gap.getValue();
newEntry.netRemoved = breakObj.netRemoved;
result.push_back(newEntry);
iBreak++;
}
if (isDirectionReversed(moveDirection)) {
std::reverse(sortedBreaks.begin(), sortedBreaks.end());
}
return result;
}
BreakList DrawBrokenView::sortBreaks(BreakList& inList, bool descend)
{
// Base::Console().Message("DBV::sortBreaks(%d, %d)\n", inList.size(), descend);
@@ -935,39 +960,61 @@ Base::Vector3d DrawBrokenView::mapPoint2dFromView(Base::Vector3d point2d) const
Base::Vector3d stdX(1.0, 0.0, 0.0);
Base::Vector3d stdY(0.0, 1.0, 0.0);
// convert point2d in view to pseudo-3d view coords
Base::Vector3d projectedCoM = projectPoint(getCompressedCentroid(), false);
// make pseudo 3d point from point2d
gp_Ax3 OXYZ;
gp_Ax3 projCS3(getProjectionCS(getCompressedCentroid()));
gp_Trsf xTo3d;
xTo3d.SetTransformation(projCS3, OXYZ);
auto pseudo3d = DU::toVector3d(DU::togp_Pnt(point2d).Transformed(xTo3d));
// now shift down and left
auto breaksAll = Breaks.getValues();
Base::Vector3d pseudo3dx = point2d + projectedCoM;
double xReverser = -1.0;
auto moveXDirection = DU::closestBasisOriented(DU::toVector3d(getProjectionCS().XDirection()));
if (isDirectionReversed(moveXDirection)) {
pseudo3dx = point2d - projectedCoM;
xReverser = 1.0;
}
// we are expanding, so the direction should be to the "left"/"down" which is the opposite of
// our XDirection
auto moveXReverser = isDirectionReversed(moveXDirection) ? 1.0 : -1.0;
bool descend = false; // should be false so we move from lowest break to highest?
auto sortedXBreaks = makeSortedBreakListCompressed(breaksAll, moveXDirection, descend);
double xLimit = pseudo3dx.x;
double xShift = shiftAmountExpand(xLimit, moveXDirection, sortedXBreaks);
Base::Vector3d xMoved = pseudo3dx + stdX * xShift * xReverser; // move to the left (-X)
auto sortedXBreaks = makeSortedBreakList(breaksAll, moveXDirection, descend);
double xLimit = DU::coordinateForDirection(pseudo3d, moveXDirection);
Base::Vector3d pseudo3dy = point2d + projectedCoM;
double yReverser = -1.0;
auto moveYDirection = DU::closestBasisOriented(DU::toVector3d(getProjectionCS().YDirection()));
if (isDirectionReversed(moveXDirection)) {
pseudo3dy = point2d - projectedCoM;
yReverser = 1.0;
std::vector<size_t> fullGaps;
int partialGapIndex{-1};
auto compressedXBreaks = makeSortedBreakListCompressed(breaksAll, moveXDirection, descend);
double partialGapPenetration = getExpandGaps(xLimit, compressedXBreaks, moveXDirection, fullGaps, partialGapIndex);
double breakSum{0};
for (auto& index : fullGaps) {
double breakSize = sortedXBreaks.at(index).netRemoved;
breakSum += breakSize;
}
descend = false;
auto sortedYBreaks = makeSortedBreakListCompressed(breaksAll, moveYDirection, descend);
double yLimit = pseudo3dy.y;
double yShift = shiftAmountExpand(yLimit, moveYDirection, sortedYBreaks);
Base::Vector3d yMoved = pseudo3dy + stdY * yShift * yReverser; // move down (-Y)
if (partialGapIndex >= 0) {
double breakSize = sortedXBreaks.at(partialGapIndex).netRemoved;
breakSum += breakSize * partialGapPenetration;
}
double xCoord2 = xLimit + breakSum * moveXReverser;
Base::Vector3d movedResult{xMoved.x, yMoved.y, 0.0};
auto moveYDirection = DU::closestBasisOriented(DU::toVector3d(getProjectionCS().YDirection()));
auto moveYReverser = isDirectionReversed(moveYDirection) ? 1.0 : -1.0;
descend = false;
auto sortedYBreaks = makeSortedBreakList(breaksAll, moveYDirection, descend);
double yLimit = DU::coordinateForDirection(pseudo3d, moveYDirection);
fullGaps.clear();
partialGapIndex = -1;
auto compressedYBreaks = makeSortedBreakListCompressed(breaksAll, moveYDirection, descend);
partialGapPenetration = getExpandGaps(yLimit, compressedYBreaks, moveYDirection, fullGaps, partialGapIndex);
breakSum = 0;
for (auto& index : fullGaps) {
double breakSize = sortedYBreaks.at(index).netRemoved;
breakSum += breakSize;
}
if (partialGapIndex >= 0) {
double breakSize = sortedYBreaks.at(partialGapIndex).netRemoved;
breakSum += breakSize * partialGapPenetration;
}
double yCoord2 = yLimit + breakSum * moveYReverser;
Base::Vector3d movedResult{xCoord2, yCoord2, 0.0};
return movedResult;
}
@@ -993,20 +1040,22 @@ double DrawBrokenView::shiftAmountShrink(double pointCoord, Base::Vector3d direc
DU::fpCompare(pointCoord, breakItem.highLimit, Precision::Confusion()) ) {
// h--------l -ve
// p
// point is left/below break, but we
shift += removedLengthFromObj(*breakItem.breakObj) - Gap.getValue();
// point is left/below break
shift += breakItem.netRemoved;
continue;
}
// h--------l -ve
// p
// g-g
// p'
// break.start < value < break.end - point is in the break area
// we move our point by a fraction of the Gap length
double penetration = fabs(pointCoord - breakItem.highLimit); // start(high) to point
double removed = removedLengthFromObj(*breakItem.breakObj);
double factor = 1 - (penetration / removed);
double netRemoved = breakItem.lowLimit - factor * Gap.getValue();
shift += fabs(netRemoved - pointCoord);
double penetration = fabs(pointCoord - breakItem.highLimit); // (p - h) start(high) to point distance
double removed = removedLengthFromObj(*breakItem.breakObj); // (h-l) full break size
double factor = 1 - (penetration / removed); // fraction of break to right
double toShift = pointCoord - (breakItem.lowLimit - factor * Gap.getValue());
shift += fabs(toShift);
} else {
@@ -1028,13 +1077,15 @@ double DrawBrokenView::shiftAmountShrink(double pointCoord, Base::Vector3d direc
// l--------h +ve
// p
// g--g
// p'
// break.start < value < break.end - point is in the break area
// we move our point by a fraction of the Gap length
double penetration = fabs(pointCoord - breakItem.lowLimit);
double removed = removedLengthFromObj(*breakItem.breakObj);
double factor = 1 - (penetration / removed);
double netRemoved = breakItem.highLimit - factor * Gap.getValue();
shift += fabs(netRemoved - pointCoord);
double netRemoved = pointCoord - breakItem.highLimit - factor * Gap.getValue();
shift += fabs(netRemoved);
}
}
@@ -1042,75 +1093,145 @@ double DrawBrokenView::shiftAmountShrink(double pointCoord, Base::Vector3d direc
}
//! returns the amount a compressed coordinate needs to be shifted to reverse the effect of breaking
//! the source shapes
double DrawBrokenView::shiftAmountExpand(double pointCoord, Base::Vector3d direction, const BreakList& sortedBreaks) const
// //! returns the amount a compressed coordinate needs to be shifted to reverse the effect of breaking
// //! the source shapes. Could have problems here if gap > removed? Is that always an error?
// double DrawBrokenView::shiftAmountExpand(double pointCoord, Base::Vector3d direction, const BreakList& sortedBreaks) const
// {
// Base::Console().Message("DBV::shiftAmountExpand(%.3f, %s, %d)\n", pointCoord,
// DU::formatVector(direction).c_str(), sortedBreaks.size());
// double shift{0};
// for (auto& breakItem : sortedBreaks) {
// if (isDirectionReversed(direction)) {
// Base::Console().Message("DBV::shiftAmountExpand - reversed\n");
// if (pointCoord <= breakItem.lowLimit) {
// // h--------l -ve
// // p
// // leave alone, this break doesn't affect us
// Base::Console().Message("DBV::shiftAmountExpand - ignore\n");
// continue;
// }
// if (pointCoord > breakItem.highLimit ||
// DU::fpCompare(pointCoord, breakItem.highLimit, Precision::Confusion()) ) {
// // h--------l -ve
// // p
// // move by the whole removed area
// shift += breakItem.netRemoved;
// Base::Console().Message("DBV::shiftAmountExpand - full\n");
// continue;
// }
// // h--------l -ve
// // p
// // break.start < value < break.end - point is in the break area
// // we move our point by the break's removed * the penetration factor
// Base::Console().Message("DBV::shiftAmountExpand - partial\n");
// double breakPenetration = fabs(pointCoord - breakItem.lowLimit);
// double removed = removedLengthFromObj(*breakItem.breakObj);
// double factor = breakPenetration / removed;
// double shiftAmount = breakItem.lowLimit + factor * removed;
// Base::Console().Message("DBV::shiftAmountExpand - penetration: %.3f removed: %.3f factor: %.3f shift: %.3f\n",
// breakPenetration, removed, factor, shiftAmount);
// shift += std::fabs(shiftAmount);
// } else {
// Base::Console().Message("DBV::shiftAmountExpand - forward\n");
// if (pointCoord >= breakItem.highLimit) {
// // l--------h +ve
// // p
// // leave alone, this break doesn't affect us
// Base::Console().Message("DBV::shiftAmountExpand - ignore\n");
// continue;
// }
// if (pointCoord < breakItem.lowLimit ||
// DU::fpCompare(pointCoord, breakItem.lowLimit, Precision::Confusion()) ) {
// // l--------h +ve
// // p
// // move by the whole removed area
// shift += breakItem.netRemoved;
// Base::Console().Message("DBV::shiftAmountExpand - full\n");
// continue;
// }
// // l--------h +ve
// // p
// // bpbpbp
// // rrrrrrrrrr
// // break.start < value < break.end - point is in the break area
// // we move our point by the break's removed * the penetration factor
// Base::Console().Message("DBV::shiftAmountExpand - partial\n");
// double breakPenetration = std::fabs(pointCoord - breakItem.highLimit); // (h-p)
// double removed = removedLengthFromObj(*breakItem.breakObj);
// double factor = breakPenetration / removed;
// double shiftAmount = breakItem.highLimit - factor * removed;
// Base::Console().Message("DBV::shiftAmountExpand - penetration: %.3f removed: %.3f factor: %.3f shift: %.3f\n",
// breakPenetration, removed, factor, shiftAmount);
// shift += std::fabs(shiftAmount);
// }
// }
// return shift;
// }
//! determine which gaps require pointCoord to move by a full gap and if there is a partial gap that must
//! be included in the move operation. If there is a partial gap, the penetration factor is returned.
//! penetration is measure right to left in the view.
double DrawBrokenView::getExpandGaps (double pointCoord,
const BreakList& compressedBreakList,
Base::Vector3d moveDirection,
std::vector<size_t>& fullGaps,
int& partialGapIndex) const
{
// Base::Console().Message("DBV::shiftAmountExpand(%.3f, %s, %d)\n", pointCoord,
// DU::formatVector(direction).c_str(), sortedBreaks.size());
double shift{0};
for (auto& breakItem : sortedBreaks) {
if (isDirectionReversed(direction)) {
if (pointCoord <= breakItem.lowLimit) {
// h--------l -ve
// p
// leave alone, this break doesn't affect us
// Base::Console().Message("DBV::getExpandGaps(coord: %.3f moveDir: %s)\n", pointCoord,
// DU::formatVector(moveDirection).c_str());
double partialPenetrationFactor{0};
// check pointCoord against compressed gaps
size_t iBreak{0};
for (auto& gap : compressedBreakList) {
if (isDirectionReversed(moveDirection)) {
// reversed X+ is to the left
if (pointCoord < gap.lowLimit) {
// not interested
iBreak++;
continue;
}
if (pointCoord > breakItem.highLimit ||
DU::fpCompare(pointCoord, breakItem.highLimit, Precision::Confusion()) ) {
// h--------l -ve
// p
// move by the whole removed area
shift += breakItem.netRemoved;
if (pointCoord > gap.highLimit ||
DU::fpCompare(pointCoord, gap.highLimit, Precision::Confusion()) ) {
// need to move by full length of associated break
fullGaps.push_back(iBreak);
iBreak++;
continue;
}
// h--------l -ve
// p
// break.start < value < break.end - point is in the break area
// we move our point by the break's net removed * the penetration factor
double gapPenetration = fabs(pointCoord - breakItem.lowLimit);
double removed = removedLengthFromObj(*breakItem.breakObj);
double factor = gapPenetration / Gap.getValue();
double shiftAmount = factor * (removed - Gap.getValue());
shift += shiftAmount;
// pointCoord is in gap
// X+ high > pointCoord > low X-
partialGapIndex = iBreak;
partialPenetrationFactor = (pointCoord - gap.lowLimit) / Gap.getValue();
iBreak++;
} else {
if (pointCoord >= breakItem.highLimit) {
// l--------h +ve
// p
// leave alone, this break doesn't affect us
// forward +X is to the right
if (pointCoord > gap.highLimit) {
// not interested
iBreak++;
continue;
}
if (pointCoord < breakItem.lowLimit ||
DU::fpCompare(pointCoord, breakItem.lowLimit, Precision::Confusion()) ) {
// l--------h +ve
// p
// move by the whole removed area
shift += breakItem.netRemoved;
if (pointCoord < gap.lowLimit ||
DU::fpCompare(pointCoord, gap.lowLimit, Precision::Confusion()) ) {
// need to move by full length of associated break
fullGaps.push_back(iBreak);
iBreak++;
continue;
}
// l--------h +ve
// p
// break.start < value < break.end - point is in the break area
// we move our point by the break's net removed * the penetration factor
double gapPenetration = pointCoord - breakItem.lowLimit;
double removed = removedLengthFromObj(*breakItem.breakObj);
double factor = 1 - gapPenetration / Gap.getValue();
double shiftAmount = factor * (removed - Gap.getValue());
shift += shiftAmount;
// pointCoord is in gap
// low < pointCoord < highLimit X+
partialGapIndex = iBreak;
partialPenetrationFactor = (gap.highLimit - pointCoord) / Gap.getValue();
iBreak++;
}
}
return shift;
}
return partialPenetrationFactor;
}
Base::Vector3d DrawBrokenView::getCompressedCentroid() const
{
if (m_compressedShape.IsNull()) {