Esempio n. 1
0
        /** Draw this object
         */
        public override void draw(IGraphics graphics)
        {
            int multiNodeCount = getMultiNodeCount();

            if (multiNodeCount == 0)
            {
                // Only the defining Beam draws the beams for all in the multi-node group
                return;
            }

            if (multiNodeCount == 1)
            {
                // DEBUG: should handle this case
                return;
            }

            FinalPoint left          = getScreenHotspot();
            double     slope         = getSlope();
            int        maxParts      = getMaxParts();
            int        stemDirection = getStemDirection();

            for (int i = 0; i < multiNodeCount; ++i)
            {
                Beam beam = getMultiNode(i);
                Beam previousBeam = null, nextBeam = null;
                if (i > 0)
                {
                    previousBeam = getMultiNode(i - 1);
                }
                if (i < (multiNodeCount - 1))
                {
                    nextBeam = getMultiNode(i + 1);
                }

                FinalPoint stemTip = beam.getAnchor().getScreenHotspot();
                // Get X and Y for this beam
                int beamX = stemTip.x;
                int beamY = (int)(left.y + slope * (beamX - left.x));

                // First, extend the stem.
                graphics.DrawLine(beamX, beamY, stemTip.x, stemTip.y);

                // For each of the possible parts, draw as needed to the left or right
                for (int part = 1; part <= maxParts; part++)
                {
                    if (i > 0)
                    {
                        // Only do parts to left if we are not the leftmost stem
                        if (part <= beam._partsToLeft && part > previousBeam._partsToRight)
                        {
                            // Draw a stub to the left
                            // DEBUG: should make sure this doesn't run into the other stem
                            drawBeam(graphics, beamX, beamY, beamX - 6);
                        }
                        // The case where the beam would extend all the way was handled
                        // by the previousBeam drawing to here.
                    }
                    if (i < (multiNodeCount - 1))
                    {
                        // Only do parts to right if we are not the rightmost stem
                        if (part <= beam._partsToRight && part > nextBeam._partsToLeft)
                        {
                            // Draw a stub to the right
                            // DEBUG: should make sure this doesn't run into the other stem
                            drawBeam(graphics, beamX, beamY, beamX + 6);
                        }
                        if (part <= beam._partsToRight && part <= nextBeam._partsToLeft)
                        {
                            // Draw beam extended over to the other
                            drawBeam(graphics, beamX, beamY,
                                     nextBeam.getAnchor().getScreenHotspot().x);
                        }
                    }

                    beamY += -stemDirection * SPACING;
                }
            }
        }
Esempio n. 2
0
        /** If this is the defining node, return the screen hotspot, computing it if
         * called for the first time.  The screen hotspot for the beam group is
         * the position of the left end of the beam group at the beam farthest from
         * the notehead.  If not the defining node, return the
         * anchor hotspot.
         * Strictly speaking, this is the hotspot of the left end of the beam, which
         * is not necessarily the defining node.
         * This also sets _maxParts and other values used internally.
         *
         * @return  The position of the hotspot in screen coordinates.
         */
        public override FinalPoint getScreenHotspot()
        {
            if (_screenHotspot != null)
            {
                // We have already computed it
                return(_screenHotspot);
            }

            int multiNodeCount = getMultiNodeCount();

            if (multiNodeCount == 0)
            {
                // Not the defining node. Just use the anchor's hot spot
                _screenHotspot = getAnchor().getScreenHotspot();
                return(_screenHotspot);
            }

            if (multiNodeCount == 1)
            {
                // This is an unexpected case with the beam on only one stem.
                _screenHotspot = getAnchor().getScreenHotspot();
                return(_screenHotspot);
            }

            // A beam is either horizontal (if the first and last stem tip are
            //   at the same y value) or slanted with one end of the beam
            //   5 points higher or lower than the beginning, based on whether
            //   the last stem tip is higher or lower.
            // Don't assume that this defining node is the leftmost, but do
            //   assume multiNode(0) is leftmost.
            // Assume the anchor for a beam is the stem whos hotspot is its tip.
            Point      hotspot   = getMultiNode(0).getAnchor().getScreenHotspot().newPoint();
            FinalPoint rightmost = getMultiNode(multiNodeCount - 1).getAnchor().getScreenHotspot();

            if (rightmost.y == hotspot.y)
            {
                _slope = 0.0;
            }
            else if (rightmost.y > hotspot.y)
            {
                _slope = 5.0 / (rightmost.x - hotspot.x);
            }
            else
            {
                _slope = -5.0 / (rightmost.x - hotspot.x);
            }

            // DEBUG: this assumes all stems in the same direction.
            _stemDirection = ((Stem)getMultiNode(0).getAnchor()).getStemDown() ? 1 : -1;

            // The Y position along the beam at x is
            //   hotspot.y + _slope * (x - hotspot.x).
            // Check each stem tip and adjust the hotspot.y as necessary
            //  to make sure the beam does not cross the stem.
            for (int i = 1; i < multiNodeCount; ++i)
            {
                FinalPoint stemTip = getMultiNode(i).getAnchor().getScreenHotspot();
                int        beamY   = (int)(hotspot.y + _slope * (stemTip.x - hotspot.x));

                // Note that larger Y is lower on the screen!
                // _stemDirection > 0 means stems down.
                if (_stemDirection > 0 && stemTip.y > beamY)
                {
                    hotspot.translate(0, stemTip.y - beamY);
                }
                else if (_stemDirection < 0 && stemTip.y < beamY)
                {
                    hotspot.translate(0, -(beamY - stemTip.y));
                }
            }

            // Compute _maxParts to be used later.
            _maxParts = 0;
            for (int i = 0; i < multiNodeCount; ++i)
            {
                Beam beam = getMultiNode(i);
                if (beam._partsToLeft > _maxParts)
                {
                    _maxParts = beam._partsToLeft;
                }
                if (beam._partsToRight > _maxParts)
                {
                    _maxParts = beam._partsToRight;
                }
            }

            // Move the hotspot to the beam farthest from the notehead.
            hotspot.translate(0, (_maxParts - 1) * _stemDirection * SPACING);

            if (_maxParts > 1)
            {
                // As a special case for 16th notes and higher, move the beams
                //  closer to the notehead.
                hotspot.translate(0, -_stemDirection * SPACING);
            }

            _screenHotspot = new FinalPoint(hotspot);
            return(_screenHotspot);
        }