All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.blaisemath.graphics.swing.render.MarkerRendererToClip Maven / Gradle / Ivy

There is a newer version: 3.0.16
Show newest version
package com.googlecode.blaisemath.graphics.swing.render;

/*
 * #%L
 * BlaiseGraphics
 * --
 * Copyright (C) 2009 - 2020 Elisha Peterson
 * --
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import static com.google.common.base.Preconditions.checkNotNull;
import com.googlecode.blaisemath.style.AttributeSet;
import com.googlecode.blaisemath.coordinate.OrientedPoint2D;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.RectangularShape;

/**
 * Draws a point along with a ray from the point to the outer edge of the graphics canvas.
 *
 * @author Elisha Peterson
 */
public class MarkerRendererToClip extends MarkerRenderer {

    /** Line style for drawing the ray */
    protected PathRenderer rayRenderer = ArrowPathRenderer.getInstance();
    /** Whether to extend in both directions, or just forward */
    protected boolean extendBothDirections = false;

    //region BUILDER PATTERNS

    /** 
     * Sets ray style and returns pointer to this object. 
     * @param rayStyle the style for rays
     * @return this
     */
    public MarkerRendererToClip rayStyle(PathRenderer rayStyle) {
        setRayRenderer(rayStyle);
        return this;
    }

    /** 
     * Sets extension rule and returns pointer to this object.
     * @param extendBoth whether to extend line in both directions
     * @return this
     */
    public MarkerRendererToClip extendBothDirections(boolean extendBoth) {
        setExtendBothDirections(extendBoth);
        return this;
    }

    //endregion

    @Override
    public String toString() {
        return String.format("PointStyleInfinite[rayStyle=%s, extendBoth=%s]", 
                rayRenderer, extendBothDirections);
    }

    //region PROPERTIES

    public PathRenderer getRayRenderer() {
        return rayRenderer;
    }

    public void setRayRenderer(PathRenderer rayStyle) {
        this.rayRenderer = checkNotNull(rayStyle);
    }

    public boolean isExtendBothDirections() {
        return extendBothDirections;
    }

    public void setExtendBothDirections(boolean extendBoth) {
        this.extendBothDirections = extendBoth;
    }
    
    //endregion

    @Override
    public void render(Point2D p, AttributeSet style, Graphics2D canvas) {
        double angle = p instanceof OrientedPoint2D ? ((OrientedPoint2D)p).angle : 0;
        Point2D p2 = new Point2D.Double(p.getX() + Math.cos(angle), p.getY() + Math.sin(angle));
        Point2D endpoint = boundaryHit(p, p2, canvas.getClipBounds());
        if (extendBothDirections) {
            Point2D endpoint1 = boundaryHit(p2, p, canvas.getClipBounds());
            rayRenderer.render(new Line2D.Double(endpoint1, endpoint), style, canvas);
        } else {
            rayRenderer.render(new Line2D.Double(p, endpoint), style, canvas);
        }
        super.render(p, style, canvas);
    }

    /**
     * Returns points at which the ray beginning at p1 and passing through p2 intersects the boundary of the window.
     * @param p1p first point
     * @param p2p second point
     * @param bounds the window boundaries
     * @return the point on the boundary
     */
    public static Point2D.Double boundaryHit(Point2D p1p, Point2D p2p, RectangularShape bounds) {
        Point2D.Double p1 = new Point2D.Double(p1p.getX(), p1p.getY());
        Point2D.Double p2 = new Point2D.Double(p2p.getX(), p2p.getY());
        if (p2.x > p1.x && p1.x <= bounds.getMaxX()) {
            // line goes to the right
            double slope = (p2.y - p1.y) / (p2.x - p1.x);
            double yRight = slope * (bounds.getMaxX() - p1.x) + p1.y;
            if (yRight <= bounds.getMaxY() && yRight >= bounds.getMinY()) {
                // point is on the right
                return new Point2D.Double(bounds.getMaxX(), yRight);
            } else if (p2.y > p1.y && p1.y <= bounds.getMaxY()) {
                // line goes up
                return new Point2D.Double((bounds.getMaxY() - p1.y) / slope + p1.x, bounds.getMaxY());
            } else if (p1.y > p2.y && p1.y >= bounds.getMinY()) {
                // line goes down
                return new Point2D.Double((bounds.getMinY() - p1.y) / slope + p1.x, bounds.getMinY());
            }
        } else if (p2.x < p1.x && p1.x >= bounds.getMinX()) {
            // line goes to the left
            double slope = (p2.y - p1.y) / (p2.x - p1.x);
            double yLeft = slope * (bounds.getMinX() - p1.x) + p1.y;
            if (yLeft <= bounds.getMaxY() && yLeft >= bounds.getMinY()) {
                // point is on the right
                return new Point2D.Double(bounds.getMinX(), yLeft);
            } else if (p2.y > p1.y && p1.y <= bounds.getMaxY()) {
                // line goes up
                return new Point2D.Double((bounds.getMaxY() - p1.y) / slope + p1.x, bounds.getMaxY());
            } else if (p1.y > p2.y && p1.y >= bounds.getMinY()) {
                // line goes down
                return new Point2D.Double((bounds.getMinY() - p1.y) / slope + p1.x, bounds.getMinY());
            }
        } else if (p1.x == p2.x) {
            // line is vertical
            if (p2.y < p1.y && p1.y >= bounds.getMinY()) {
                // line goes up
                return new Point2D.Double(p1.x, bounds.getMinY());
            } else if (p1.y <= bounds.getMaxY()) {
                return new Point2D.Double(p1.x, bounds.getMaxY());
            }
        }
        return new Point2D.Double(p2.x, p2.y);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy