org.kalypso.model.wspm.ui.profil.dialogs.reducepoints.SimplifyProfileOperation.java Source code

Java tutorial

Introduction

Here is the source code for org.kalypso.model.wspm.ui.profil.dialogs.reducepoints.SimplifyProfileOperation.java

Source

/*----------------    FILE HEADER KALYPSO ------------------------------------------
 *
 *  This file is part of kalypso.
 *  Copyright (C) 2004 by:
 *
 *  Technical University Hamburg-Harburg (TUHH)
 *  Institute of River and coastal engineering
 *  Denickestrae 22
 *  21073 Hamburg, Germany
 *  http://www.tuhh.de/wb
 *
 *  and
 *
 *  Bjoernsen Consulting Engineers (BCE)
 *  Maria Trost 3
 *  56070 Koblenz, Germany
 *  http://www.bjoernsen.de
 *
 *  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 2.1 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; without 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
 *
 *  Contact:
 *
 *  E-Mail:
 *  belger@bjoernsen.de
 *  schlienger@bjoernsen.de
 *  v.doemming@tuhh.de
 *
 *  ---------------------------------------------------------------------------*/
package org.kalypso.model.wspm.ui.profil.dialogs.reducepoints;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.IOperationHistory;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.PlatformUI;
import org.kalypso.model.wspm.core.profil.IProfile;
import org.kalypso.model.wspm.core.profil.changes.PointRemove;
import org.kalypso.model.wspm.core.profil.operation.ProfileOperation;
import org.kalypso.model.wspm.core.profil.operation.ProfileOperationRunnable;
import org.kalypso.model.wspm.core.profil.util.DouglasPeuckerHelper;
import org.kalypso.model.wspm.core.profil.wrappers.IProfileRecord;
import org.kalypso.model.wspm.ui.KalypsoModelWspmUIPlugin;
import org.kalypso.model.wspm.ui.i18n.Messages;

/**
 * @author Gernot Belger
 */
public class SimplifyProfileOperation {
    private final IProfile m_profile;

    private final IPointsProvider m_provider;

    private final double m_distance;

    private final String[] m_buildingComponents;

    private ProfileOperation m_operation;

    public SimplifyProfileOperation(final IProfile profile, final IPointsProvider provider, final double distance,
            final String[] buildingComponents) {
        m_profile = profile;
        m_provider = provider;
        m_distance = distance;
        m_buildingComponents = buildingComponents;
    }

    public Pair<IProfileRecord[], IStatus> findPointsToRemove() {
        if (m_provider == null || Double.isNaN(m_distance)) {
            final IStatus status = new Status(IStatus.WARNING, KalypsoModelWspmUIPlugin.ID, Messages
                    .getString("org.kalypso.model.wspm.ui.profil.dialogs.reducepoints.DouglasPeuckerDialog.11")); //$NON-NLS-1$
            return Pair.of(null, status);
        }

        /* Get important values. */
        final double allowedDistance = m_distance;
        final IProfileRecord[] points = m_provider.getPoints();

        /* Find out which points to keep */
        final IProfileRecord[] pointsToKeep = getPointsToKeep();

        /* Get the profile changes. */

        final IProfileRecord[] pointsToRemove = DouglasPeuckerHelper.reducePoints(points, pointsToKeep,
                allowedDistance);
        if (pointsToRemove.length == 0) {
            final IStatus status = new Status(IStatus.INFO, KalypsoModelWspmUIPlugin.ID, Messages
                    .getString("org.kalypso.model.wspm.ui.profil.dialogs.reducepoints.DouglasPeuckerDialog.12")); //$NON-NLS-1$
            return Pair.of(null, status);
        }

        /* Message for the user. */
        final String message = Messages.getString(
                "org.kalypso.model.wspm.ui.profil.dialogs.reducepoints.DouglasPeuckerDialog.14", //$NON-NLS-1$
                pointsToRemove.length, points.length);

        final IStatus status = new Status(IStatus.INFO, KalypsoModelWspmUIPlugin.ID, message);
        return Pair.of(pointsToRemove, status);
    }

    public IStatus doRemovePoints() {
        final Pair<IProfileRecord[], IStatus> result = findPointsToRemove();

        final IProfileRecord[] pointsToRemove = result.getKey();
        final IStatus reduceStatus = result.getValue();

        if (pointsToRemove == null)
            return reduceStatus;

        /* Create the profile operation. */
        final PointRemove pointRemove = new PointRemove(m_profile, pointsToRemove);
        m_operation = new ProfileOperation(
                Messages.getString("org.kalypso.model.wspm.ui.profil.dialogs.reducepoints.DouglasPeuckerDialog.13"), //$NON-NLS-1$
                m_profile, pointRemove, false);

        /* Create the runnable. */
        final ProfileOperationRunnable operationRunnable = new ProfileOperationRunnable(m_operation);

        /* Execute the value. */
        final IStatus operationStatus = operationRunnable.execute(new NullProgressMonitor());
        if (!operationStatus.isOK())
            return operationStatus;

        return reduceStatus;
    }

    private IProfileRecord[] getPointsToKeep() {
        final Collection<IProfileRecord> pointsToKeep = new ArrayList<>();

        /* Marked points (TF, DB, BV) should never get simplified */
        final IProfileRecord[] markedPoints = m_profile.getMarkedPoints();
        pointsToKeep.addAll(Arrays.asList(markedPoints));

        /*
         * TODO: in order to do a correct simplifikatino with bridges/weirs, we need to split up the simplifikation in
         * several chunks per bridge-part.
         */

        /* for now, we just keep all bridge points, which does not work if all points are bridge points */
        final IProfileRecord[] buildingPoints = getBuildingPoints(m_profile);
        pointsToKeep.addAll(Arrays.asList(buildingPoints));

        return pointsToKeep.toArray(new IProfileRecord[pointsToKeep.size()]);
    }

    private IProfileRecord[] getBuildingPoints(final IProfile profile) {
        final Collection<IProfileRecord> buildingPoints = new ArrayList<>();

        for (final String buildingComponent : m_buildingComponents) {
            final IProfileRecord[] componentPoints = getBuildingPoints(profile, buildingComponent);
            buildingPoints.addAll(Arrays.asList(componentPoints));
        }

        return buildingPoints.toArray(new IProfileRecord[buildingPoints.size()]);
    }

    private IProfileRecord[] getBuildingPoints(final IProfile profile, final String buildingComponent) {
        if (!ArrayUtils.isEmpty(m_buildingComponents))
            return getAllValidPoints(profile, buildingComponent);

        return getStartingEndBuildingPoints(profile, buildingComponent);
    }

    /**
     * Get all profile points of a component, which values are of type number (i.e non-<code>null</code>).
     */
    private IProfileRecord[] getAllValidPoints(final IProfile profile, final String buildingComponent) {
        final Collection<IProfileRecord> allPoints = new ArrayList<>();

        final int componentIndex = profile.indexOfProperty(buildingComponent);
        if (componentIndex == -1)
            return new IProfileRecord[0];

        final IProfileRecord[] points = profile.getPoints();
        for (final IProfileRecord point : points) {
            final Object value = point.getValue(componentIndex);
            if (value instanceof Number) {
                allPoints.add(point);
            }
        }

        return allPoints.toArray(new IProfileRecord[allPoints.size()]);
    }

    // FIXME: does not work properly we need to consider if the point lies on the soil or not, see BridgeRule
    @SuppressWarnings("unused")
    private IProfileRecord[] getStartingEndBuildingPoints(final IProfile profile, final String buildingComponent) {
        final Collection<IProfileRecord> startOrEndPoints = new HashSet<IProfileRecord>();

        // final int componentIndex = profile.indexOfProperty( buildingComponent );
        // if( componentIndex == -1 )
        // return new IRecord[0];
        //
        // final IRecord[] points = profile.getPoints();
        //
        // boolean lastValid = false;
        // IRecord lastPoint = null;
        // for( final IRecord point : points )
        // {
        // final Object value = point.getValue( componentIndex );
        // final boolean isValid = value instanceof Number;
        //
        // /* Start point */
        // if( isValid && !lastValid )
        // startOrEndPoints.add( point );
        //
        // if( !isValid && lastValid && lastPoint != null )
        // startOrEndPoints.add( lastPoint );
        //
        // lastValid = isValid;
        // lastPoint = point;
        // }

        return startOrEndPoints.toArray(new IProfileRecord[startOrEndPoints.size()]);
    }

    public IStatus resetLastOperation() throws ExecutionException {
        if (m_operation == null)
            return Status.OK_STATUS;

        final IOperationHistory operationHistory = PlatformUI.getWorkbench().getOperationSupport()
                .getOperationHistory();
        final IStatus status = operationHistory.undoOperation(m_operation, new NullProgressMonitor(), null);
        m_operation = null;
        return status;
    }
}