Adjust scale arround parts

Hello,

Is there exist a function like Part.CenterPart to adjust scale to view a list of part.

The issue is to scale the diagram enough (zoom-in or out) to see a selection of part.
(selected by selection tool or programmaticaly)

Here’s an idea of my code :

private void Adjust(IEnumerable<Part> oPartList)
        {
            double dXMin = double.NaN;
            double dYMin = double.NaN;
            double dXMax = double.NaN;
            double dYMax = double.NaN;

            Rect oBound;
            foreach (Part oPart in oPartList)
            {
                oBound = oPart.Bounds;
                dXMin = double.IsNaN(dXMin) ? oBound.X : Math.Min(oBound.X, dXMin);
                dYMin = double.IsNaN(dYMin) ? oBound.Y : Math.Min(oBound.Y, dYMin);
                dXMax = double.IsNaN(dXMax) ? oBound.X + oBound.Width : Math.Max(oBound.X + oBound.Width, dXMax);
                dYMax = double.IsNaN(dYMax) ? oBound.Y + oBound.Height : Math.Max(oBound.Y + oBound.Height, dYMax);
            }

            DiagramPanel oPanel = myDiagram.Panel;
            double dWCurrent = oPanel.ViewportBounds.Width;
            double dHCurrent = oPanel.ViewportBounds.Height;
            double dScaleCurrent = oPanel.Scale;

            double dWNew = dXMax - dXMin;
            double dHNew = dYMax - dYMin;

            double dScaleNew = Math.Min( dWNew * dScaleCurrent / dWCurrent,
                dHNew * dScaleCurrent / dHCurrent);
            oPanel.Scale = dScaleNew;

            //CenterPanelOn(new Point(dWNew / 2, dHNew / 2));
        }

My problem is on new scale calculating… in most cases I want to zoom in, but my algorithm perform a zoom out.

Finally I’d like to center my wanted rectangle in the viewport.

Have you an idea ?

Hi AuroreErgole!
I had recently similar problems. I wrote the following code.
I hope it helps to solve your problem.
Lukas

/// <summary>
/// Moves the DiagramPanel.Viewport to the given Spot of the DiagramPanel without the DiagramPanel.Padding.
/// </summary>
/// <param name="viewSpot">the target-spot</param>
private void ShowSpot(Spot viewSpot)
{
    DiagramPanel myPanel = myDiagram.Panel;
    Thickness myPadding = myPanel.Padding;
    double myScale = myPanel.Scale;

    double diagramWidth = myPanel.ExtentWidth - (myPadding.Left + myPadding.Right) * myScale;
    double diagramHeight = myPanel.ExtentHeight - (myPadding.Top + myPadding.Bottom) * myScale;

    myPanel.SetHorizontalOffset(myPadding.Left * myScale + (diagramWidth - myPanel.ViewportWidth) * viewSpot.X - viewSpot.OffsetX * myScale);
    myPanel.SetVerticalOffset(myPadding.Top * myScale + (diagramHeight - myPanel.ViewportHeight) * viewSpot.Y - viewSpot.OffsetY * myScale);
}

/// <summary>
/// Set the scale of the DiagramPanel that all Nodes fit into the DiagramPanel.Viewport.
/// If the scale would be less than <param name="minScale"/> the scale is set to <param name="minScale"/>.
/// If the scale would be greater than <param name="maxScale"/> the scale is set to <param name="maxScale"/>.
/// </summary>
/// <param name="minScale">The minimum scale that is allowed. If it is less than or equal to 0 it will be ignored.</param>
/// <param name="maxScale">The maximum scale that is allowed. If it is less than or equal to <param name="minScale"/> it will be ignored.</param>
/// <param name="emptyHorizontalSpace">The space that should be empty on the left and right side (altogether) of the nodes if possible without setting the scale less than <param name="minScale"/>.</param>
/// <param name="emptyVerticalSpace">The space that should be empty on the top and bottom side (altogether) of the nodes if possible without setting the scale less than <param name="minScale"/>.</param>
/// <returns>
/// 0 if the scale had been between <param name="minScale"/> and <param name="maxScale"/>.
/// -1 if the scale had been less than <param name="minScale"/>.
/// +1 if the scale had been greater than <param name="maxScale"/>.
/// </returns>
private int SetScale_AllNodesFitIntoViewport(double minScale, double maxScale, double emptyHorizontalSpace, double emptyVerticalSpace)
{
    DiagramPanel myPanel = myDiagram.Panel;
    Thickness myPadding = myPanel.Padding;
    double optimalHorizontalScale = myPanel.ViewportWidth / (myPanel.DiagramBounds.Width - myPadding.Left - myPadding.Right + emptyHorizontalSpace);
    double optimalVerticalScale = myPanel.ViewportHeight / (myPanel.DiagramBounds.Height - myPadding.Top - myPadding.Bottom + emptyVerticalSpace);
    double optimalScale = optimalHorizontalScale <= optimalVerticalScale ? optimalHorizontalScale : optimalVerticalScale;

    if (minScale > 0 && optimalScale < minScale)
    {
        myPanel.Scale = minScale;
        return -1;
    }
    else if (maxScale > minScale && optimalScale > maxScale)
    {
        myPanel.Scale = maxScale;
        return 1;
    }
    else
    {
        myPanel.Scale = optimalScale;
        return 0;
    }
}

Also, DiagramPanel.ComputeBounds will produce the union of the Part.Bounds. You just need to check for a return value of Rect.Empty, in case there weren’t any parts or if they didn’t have valid bounds.