Skip to content

Commit

Permalink
Improve autoplace by adding padding
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-spa committed Jun 6, 2024
1 parent c6815e6 commit 6ea9fc6
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 15 deletions.
26 changes: 26 additions & 0 deletions src/engraving/infrastructure/skyline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,22 @@ void SkylineLine::add(const Shape& s)
}
}

SkylineLine SkylineLine::getFilteredCopy(std::function<bool(const ShapeElement&)> filterOut) const
{
SkylineLine newSkylineLine(*this);

newSkylineLine.m_shape.clear();

for (const ShapeElement& shapeEl : m_shape.elements()) {
if (filterOut(shapeEl)) {
continue;
}
newSkylineLine.m_shape.add(shapeEl);
}

return newSkylineLine;
}

void SkylineLine::add(const ShapeElement& r)
{
if (r.ignoreForLayout()) {
Expand Down Expand Up @@ -200,6 +216,16 @@ double SkylineLine::minDistance(const SkylineLine& sl, double minHorizontalClear
return m_shape.minVerticalDistance(sl.m_shape, minHorizontalClearance);
}

double SkylineLine::minDistanceToShapeAbove(const Shape& shapeAbove, double minHorizontalClearance) const
{
return shapeAbove.minVerticalDistance(m_shape, minHorizontalClearance);
}

double SkylineLine::minDistanceToShapeBelow(const Shape& shapeBelow, double minHorizontalClearance) const
{
return m_shape.minVerticalDistance(shapeBelow, minHorizontalClearance);
}

double SkylineLine::verticalClearanceAbove(const Shape& shapeAbove) const
{
return shapeAbove.verticalClearance(m_shape);
Expand Down
3 changes: 3 additions & 0 deletions src/engraving/infrastructure/skyline.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,14 @@ class SkylineLine

template<typename Predicate>
inline bool remove_if(Predicate p) { return m_shape.remove_if(p); }
SkylineLine getFilteredCopy(std::function<bool(const ShapeElement&)> filterOut) const;

void clear();
// TODO: avoid passing down minHorizontalClearance (in future it must be done
// item-by-item similar to what we do for horizontal spacing)
double minDistance(const SkylineLine&, double minHorizontalClearance = 0.0) const;
double minDistanceToShapeAbove(const Shape&, double minHorizontalClearance = 0.0) const;
double minDistanceToShapeBelow(const Shape&, double minHorizontalClearance = 0.0) const;
double verticalClearanceAbove(const Shape& shapeAbove) const;
double verticalClaranceBelow(const Shape& shapeBelow) const;
double max() const;
Expand Down
25 changes: 15 additions & 10 deletions src/engraving/rendering/dev/autoplace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ void Autoplace::autoplaceSegmentElement(const EngravingItem* item, EngravingItem
rebase = rebaseOffset(item, ldata);
}

const double minSkylineHorizontalClearance = item->style().styleMM(Sid::skylineMinHorizontalClearance) * item->mag();

if (item->autoplace() && item->explicitParent()) {
const Segment* s = toSegment(item->explicitParent());
const Measure* m = s->measure();
Expand Down Expand Up @@ -74,15 +76,17 @@ void Autoplace::autoplaceSegmentElement(const EngravingItem* item, EngravingItem
shape.translate(PointF(0.0, stYOffset));
}

SkylineLine sk(!above);
double d;
if (above) {
sk.add(shape);
d = sk.minDistance(ss->skyline().north());
} else {
sk.add(shape);
d = ss->skyline().south().minDistance(sk);
}
SkylineLine& staffSkyline = above ? ss->skyline().north() : ss->skyline().south();

SkylineLine filteredSkyline = staffSkyline.getFilteredCopy([item](const ShapeElement& shapeEl) {
const EngravingItem* shapeItem = shapeEl.item();
return shapeItem && shapeItem->parent() == item->parent()
&& (item->isDynamic() || item->isExpression())
&& (shapeItem->isDynamic() || shapeItem->isExpression());
});

double d = above ? filteredSkyline.minDistanceToShapeAbove(shape, minSkylineHorizontalClearance)
: filteredSkyline.minDistanceToShapeBelow(shape, minSkylineHorizontalClearance);

if (d > -minDistance) {
double yd = d + minDistance;
Expand All @@ -100,8 +104,9 @@ void Autoplace::autoplaceSegmentElement(const EngravingItem* item, EngravingItem
ldata->moveY(yd);
shape.translate(PointF(0.0, yd));
}

if (add && item->addToSkyline()) {
ss->skyline().add(shape);
staffSkyline.add(shape);
}
}
setOffsetChanged(item, ldata, false);
Expand Down
14 changes: 9 additions & 5 deletions src/engraving/rendering/dev/systemlayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2806,12 +2806,16 @@ void SystemLayout::centerElementBetweenStaves(EngravingItem* element, const Syst
.adjust(-minHorizontalClearance, 0.0, minHorizontalClearance, 0.0);
elementShape.remove_if([](ShapeElement& shEl) { return shEl.ignoreForLayout(); });

// Take a *copy* of the skyline of this staff
SkylineLine thisSkyline = isAbove ? thisStaff->skyline().north() : thisStaff->skyline().south();
thisSkyline.remove_if([element](ShapeElement& shEl) {
const SkylineLine& skylineOfThisStaff = isAbove ? thisStaff->skyline().north() : thisStaff->skyline().south();

SkylineLine thisSkyline = skylineOfThisStaff.getFilteredCopy([element](const ShapeElement& shEl) {
const EngravingItem* shapeItem = shEl.item();
return shapeItem && (shapeItem == element || shapeItem->parentItem(true) == element || shapeItem->isAccidental()
|| shapeItem == element->ldata()->itemSnappedBefore() || shapeItem == element->ldata()->itemSnappedAfter());
if (!shapeItem) {
return false;
}
return shapeItem == element || shapeItem->parentItem(true) == element || shapeItem->type() == element->type()
|| shapeItem->isAccidental() || shapeItem == element->ldata()->itemSnappedBefore()
|| shapeItem == element->ldata()->itemSnappedAfter();
});

double yStaffDiff = nextStaff->y() - thisStaff->y();
Expand Down

0 comments on commit 6ea9fc6

Please sign in to comment.