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

org.dishevelled.piccolo.venn.Centers Maven / Gradle / Ivy

There is a newer version: 1.1
Show newest version
/*

    dsh-piccolo-venn  Piccolo2D venn diagram nodes and supporting classes.
    Copyright (c) 2009-2013 held jointly by the individual authors.

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published
    by the Free Software Foundation; either version 3 of the License, or (at
    your option) any later version.

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
    License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this library;  if not, write to the Free Software Foundation,
    Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.

    > http://www.fsf.org/licensing/licenses/lgpl.html
    > http://www.opensource.org/licenses/lgpl-license.php

*/
package org.dishevelled.piccolo.venn;

import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;

import org.dishevelled.evolve.EvolutionaryAlgorithm;
import org.dishevelled.evolve.ExitStrategy;
import org.dishevelled.evolve.Fitness;
import org.dishevelled.evolve.Mutation;
import org.dishevelled.evolve.Recombination;
import org.dishevelled.evolve.Selection;
import org.dishevelled.evolve.exit.TimeLimitExitStrategy;
import org.dishevelled.evolve.impl.EvolutionaryAlgorithmImpl;
import org.dishevelled.evolve.recombine.SexualRecombination;
import org.dishevelled.evolve.select.FitnessProportionalSelection;

/**
 * Utility methods for finding the center of areas.
 *
 * @author  Michael Heuer
 * @version $Revision$ $Date$
 */
final class Centers
{
    /** Number of individuals, 100. */
    private static final int INDIVIDUALS = 100;

    /** Time limit in generations, 75. */
    private static final int GENERATIONS = 75;


    /**
     * Private no-arg constructor.
     */
    private Centers()
    {
        // empty
    }


    /**
     * Find and return the center of the specified shape using its bounds rectangle.
     *
     * @param shape shape, must not be null
     * @return the center of the specified shape using its bounds rectangle
     */
    static Point2D centerOf(final Shape shape)
    {
        return centerOf(shape, new Point2D.Double());
    }

    /**
     * Find and return the specified center of the specified shape using its bounds rectangle.
     *
     * @param shape shape, must not be null
     * @param center center, must not be null
     * @return the specified center of the specified shape using its bounds rectangle
     */
    static Point2D centerOf(final Shape shape, final Point2D center)
    {
        if (shape == null)
        {
            throw new IllegalArgumentException("shape must not be null");
        }
        return centerOf(shape.getBounds2D(), center);
    }

    /**
     * Find and return the center of the specified rectangle.
     *
     * @param rectangle rectangle, must not be null
     * @return the center of the specified rectangle
     */
    static Point2D centerOf(final Rectangle2D rectangle)
    {
        return centerOf(rectangle, new Point2D.Double());
    }

    /**
     * Find and return the specified center of the specified rectangle.
     *
     * @param rectangle rectangle, must not be null
     * @param center center, must not be null
     * @return the specified center of the specified rectangle
     */
    static Point2D centerOf(final Rectangle2D rectangle, final Point2D center)
    {
        if (rectangle == null)
        {
            throw new IllegalArgumentException("rectangle must not be null");
        }
        if (center == null)
        {
            throw new IllegalArgumentException("center must not be null");
        }
        center.setLocation(rectangle.getCenterX(), rectangle.getCenterY());
        return center;
    }

    /**
     * Find and return the center of the specified area using its bounds rectangle.
     *
     * @param area area, must not be null
     * @return the center of the specified area using its bounds rectangle
     */
    static Point2D centerOf(final Area area)
    {
        return centerOf(area, new Point2D.Double());
    }

    /**
     * Find and return the specified center of the specified area using its bounds rectangle.
     *
     * @param area area, must not be null
     * @param center center, must not be null
     * @return the specified center of the specified area using its bounds rectangle
     */
    static Point2D centerOf(final Area area, final Point2D center)
    {
        if (area == null)
        {
            throw new IllegalArgumentException("area must not be null");
        }
        return centerOf(area.getBounds2D(), center);
    }

    /**
     * Find and return an approximate centroid of the specified area using
     * an evolutionary algorithm.
     *
     * @param area area, must not be null
     * @return an approximate centroid of the specified area using an
     *    evolutionary algorithm
     */
    static Point2D centroidOf(final Area area)
    {
        return centroidOf(area, new Point2D.Double());
    }

    /**
     * Find and return the specified approximate centroid of the specified area using
     * an evolutionary algorithm.
     *
     * @param area area, must not be null
     * @param centroid centroid, must not be null
     * @return the specified approximate centroid of the specified area using an
     *    evolutionary algorithm
     */
    static Point2D centroidOf(final Area area, final Point2D centroid)
    {
        return centroidOf(area, centroid, new Random());
    }

    /**
     * Find and return the specified approximate centroid of the specified area using
     * an evolutionary algorithm.
     *
     * @param area area, must not be null
     * @param centroid centroid, must not be null
     * @param random source of randomness
     * @return the specified approximate centroid of the specified area using an
     *    evolutionary algorithm
     */
    static Point2D centroidOf(final Area area, final Point2D centroid, final Random random)
    {
        if (area == null)
        {
            throw new IllegalArgumentException("area must not be null");
        }
        if (centroid == null)
        {
            throw new IllegalArgumentException("centroid must not be null");
        }
        if (random == null)
        {
            throw new IllegalArgumentException("random must not be null");
        }

        final Rectangle2D bounds = area.getBounds2D();
        List individuals = new ArrayList(INDIVIDUALS);
        for (int i = 0; i < INDIVIDUALS; i++)
        {
            double x = bounds.getX() + random.nextDouble() * bounds.getWidth();
            double y = bounds.getY() + random.nextDouble() * bounds.getHeight();
            individuals.add(new Point2D.Double(x, y));
        }
        ExitStrategy exitStrategy = new TimeLimitExitStrategy(GENERATIONS);
        Selection selection = new FitnessProportionalSelection();

        Recombination recombination = new SexualRecombination()
            {
                private double x = 0.0d;
                private double y = 0.0d;

                @Override
                public Point2D recombine(final Point2D individual0, final Point2D individual1)
                {
                    x = (individual0.getX() + individual1.getX()) / 2.0d;
                    y = (individual0.getY() + individual1.getY()) / 2.0d;
                    return new Point2D.Double(x, y);
                }
            };

        Mutation mutation = new Mutation()
            {
                private double x = 0.0d;
                private double y = 0.0d;

                @Override
                public Collection mutate(final Collection recombined)
                {
                    for (Point2D point : recombined)
                    {
                        x = point.getX() + random.nextDouble() * 2.0d - random.nextDouble() * 2.0d;
                        y = point.getY() + random.nextDouble() * 2.0d - random.nextDouble() * 2.0d;
                        point.setLocation(x, y);
                    }
                    return recombined;
                }
            };

        Fitness fitness = new Fitness()
            {
                private double leastXDistance;
                private double leastYDistance;
                private final Point2D query = new Point2D.Double();
                private Area vertical;
                private Area horizontal;
                private Rectangle2D horizontalBounds;
                private Rectangle2D verticalBounds;
                private final Rectangle2D v = new Rectangle2D.Double();
                private final Rectangle2D h = new Rectangle2D.Double();


                @Override
                public Double score(final Point2D individual)
                {
                    if (!area.contains(individual))
                    {
                        return Double.valueOf(0.0d);
                    }
                    query.setLocation(individual.getX(), individual.getY());

                    v.setRect(query.getX(), bounds.getY(), 1.0d, bounds.getY() + bounds.getHeight());
                    vertical = new Area(v);
                    vertical.intersect(area);
                    verticalBounds = vertical.getBounds2D();
                    leastYDistance = Math.min(Math.abs(query.getY() - verticalBounds.getY()),
                                              Math.abs(verticalBounds.getY() + verticalBounds.getHeight() - query.getY()));

                    h.setRect(bounds.getX(), query.getY(), bounds.getX() + bounds.getWidth(), 1.0d);
                    horizontal = new Area(h);
                    horizontal.intersect(area);
                    horizontalBounds = horizontal.getBounds2D();
                    leastXDistance = Math.min(Math.abs(query.getX() - horizontalBounds.getX()),
                                              Math.abs(horizontalBounds.getX() + horizontalBounds.getWidth() - query.getX()));

                    return Double.valueOf(leastXDistance + leastYDistance);
                }
            };

        double maxFitness = 0.0d;
        Point2D max = null;
        EvolutionaryAlgorithm ea = new EvolutionaryAlgorithmImpl();
        for (Point2D point : ea.evolve(individuals, exitStrategy, recombination, mutation, fitness, selection))
        {
            double f = fitness.score(point);
            if (f > maxFitness)
            {
                maxFitness = f;
                max = point;
            }
        }
        centroid.setLocation(max.getX(), max.getY());
        return centroid;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy