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

com.github.rinde.rinsim.examples.demo.factory.BoxRenderer Maven / Gradle / Ivy

/*
 * Copyright (C) 2011-2017 Rinde van Lon, imec-DistriNet, KU Leuven
 *
 * 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.
 */
package com.github.rinde.rinsim.examples.demo.factory;

import static com.google.common.base.Preconditions.checkState;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nullable;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Transform;

import com.github.rinde.rinsim.core.model.DependencyProvider;
import com.github.rinde.rinsim.core.model.ModelBuilder.AbstractModelBuilder;
import com.github.rinde.rinsim.core.model.pdp.PDPModel;
import com.github.rinde.rinsim.core.model.pdp.PDPModel.ParcelState;
import com.github.rinde.rinsim.core.model.pdp.PDPModel.VehicleState;
import com.github.rinde.rinsim.core.model.pdp.Parcel;
import com.github.rinde.rinsim.core.model.pdp.Vehicle;
import com.github.rinde.rinsim.core.model.road.RoadModel;
import com.github.rinde.rinsim.geom.Point;
import com.github.rinde.rinsim.ui.renderers.CanvasRenderer.AbstractCanvasRenderer;
import com.github.rinde.rinsim.ui.renderers.UiSchema;
import com.github.rinde.rinsim.ui.renderers.ViewPort;
import com.google.auto.value.AutoValue;

class BoxRenderer extends AbstractCanvasRenderer {
  static final float AT_SITE_ROTATION = 0f;
  static final float IN_CARGO_ROTATION = 20f;
  static final Point LABEL_OFFSET = new Point(-15, -40);
  static final double MAX_PERC = 100d;

  ImageType img;

  enum ImageType {

    SMALL("/graphics/perspective/deliverypackage2.png", new Point(-12, -13),
        new Point(-21, -1)),

    LARGE("/graphics/perspective/deliverypackage3.png", new Point(-20, -21),
        new Point(-23, -8));

    final String file;
    final Point atSiteOffset;
    final Point inCargoOffset;

    ImageType(String f, Point atSite, Point inCargo) {
      file = f;
      atSiteOffset = atSite;
      inCargoOffset = inCargo;
    }

  }

  RoadModel roadModel;
  PDPModel pdpModel;
  final UiSchema uiSchema;

  BoxRenderer(RoadModel rm, PDPModel pm) {
    img = ImageType.LARGE;
    roadModel = rm;
    pdpModel = pm;
    uiSchema = new UiSchema(false);
    uiSchema.add(Box.class, img.file);
  }

  @Override
  public void renderStatic(GC gc, ViewPort vp) {}

  @Override
  public void renderDynamic(GC gc, ViewPort vp, long time) {
    uiSchema.initialize(gc.getDevice());

    final Collection parcels = pdpModel.getParcels(
      ParcelState.values());
    final Image image = uiSchema.getImage(Box.class);
    checkState(image != null);

    synchronized (pdpModel) {
      final Set vehicles = pdpModel.getVehicles();
      final Map mapping = new LinkedHashMap<>();
      for (final Vehicle v : vehicles) {
        for (final Parcel p : pdpModel.getContents(v)) {
          mapping.put(p, v);
        }
        if (pdpModel.getVehicleState(v) != VehicleState.IDLE) {
          final PDPModel.VehicleParcelActionInfo vpai = pdpModel
            .getVehicleActionInfo(v);
          mapping.put(vpai.getParcel(), vpai.getVehicle());
        }
      }

      for (final Parcel p : parcels) {
        drawBox(p, gc, vp, time, image, mapping);
      }
    }
  }

  @SuppressWarnings("unused")
  void drawBox(Parcel p, GC gc, ViewPort vp, long time, Image image,
      Map mapping) {
    float rotation = AT_SITE_ROTATION;
    int offsetX = 0;
    int offsetY = 0;
    @Nullable
    final ParcelState ps = pdpModel.getParcelState(p);
    if (ps == null) {
      return;
    }
    if (ps == ParcelState.AVAILABLE) {
      final Point pos = roadModel.getPosition(p);
      final int x = vp.toCoordX(pos.x);
      final int y = vp.toCoordY(pos.y);
      offsetX = (int) img.atSiteOffset.x + x - image.getBounds().width / 2;
      offsetY = (int) img.atSiteOffset.y + y - image.getBounds().height / 2;
    } else if (ps == ParcelState.PICKING_UP || ps == ParcelState.DELIVERING) {

      final Vehicle v = mapping.get(p);
      final PDPModel.VehicleParcelActionInfo vpai = pdpModel
        .getVehicleActionInfo(v);
      final Point pos = roadModel.getPosition(v);
      final int x = vp.toCoordX(pos.x);
      final int y = vp.toCoordY(pos.y);
      final double percentage = 1d - vpai.timeNeeded()
        / (double) p.getPickupDuration();
      final String text = (int) (percentage * MAX_PERC) + "%";

      final float rotFac =
        (float) (ps == ParcelState.PICKING_UP ? percentage
          : 1d - percentage);
      rotation = IN_CARGO_ROTATION * rotFac;

      final int textWidth = gc.textExtent(text).x;
      gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_BLUE));
      gc.drawText(text, (int) LABEL_OFFSET.x + x - textWidth / 2,
        (int) LABEL_OFFSET.y + y, true);

      Point from = new Point(img.atSiteOffset.x + x
        - image.getBounds().width
          / 2d,
        img.atSiteOffset.y + y - image.getBounds().height / 2d);
      Point to = new Point(img.inCargoOffset.x + x
        - image.getBounds().width
          / 2d,
        img.inCargoOffset.y + y - image.getBounds().height / 2d);

      if (ps == ParcelState.DELIVERING) {
        final Point temp = from;
        from = to;
        to = temp;
      }

      final Point diff = Point.diff(to, from);
      offsetX = (int) (from.x + percentage * diff.x);
      offsetY = (int) (from.y + percentage * diff.y);

    } else if (ps == ParcelState.IN_CARGO) {
      rotation = IN_CARGO_ROTATION;
      final Point pos = roadModel.getPosition(mapping.get(p));
      final int x = vp.toCoordX(pos.x);
      final int y = vp.toCoordY(pos.y);
      offsetX = (int) img.inCargoOffset.x + x - image.getBounds().width / 2;
      offsetY = (int) img.inCargoOffset.y + y - image.getBounds().height
        / 2;
    }

    if (!ps.isDelivered()) {
      if (rotation == 0f) {
        gc.drawImage(image, offsetX, offsetY);
      } else {
        final Transform oldTransform = new Transform(gc.getDevice());
        gc.getTransform(oldTransform);

        final Transform transform = new Transform(gc.getDevice());
        transform.translate(offsetX + image.getBounds().width / 2, offsetY
          + image.getBounds().height / 2);
        transform.rotate(rotation);
        transform.translate(-(offsetX + image.getBounds().width / 2),
          -(offsetY + image.getBounds().height / 2));
        gc.setTransform(transform);
        gc.drawImage(image, offsetX, offsetY);
        gc.setTransform(oldTransform);
        transform.dispose();
        oldTransform.dispose();
      }
    }
  }

  static Builder builder() {
    return new AutoValue_BoxRenderer_Builder();
  }

  @AutoValue
  abstract static class Builder
      extends AbstractModelBuilder {
    private static final long serialVersionUID = 3349625514419113101L;

    Builder() {
      setDependencies(RoadModel.class, PDPModel.class);
    }

    @Override
    public BoxRenderer build(DependencyProvider dependencyProvider) {
      final RoadModel rm = dependencyProvider.get(RoadModel.class);
      final PDPModel pm = dependencyProvider.get(PDPModel.class);
      return new BoxRenderer(rm, pm);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy