playground.gregor.vis.CASimVisClient.java Source code

Java tutorial

Introduction

Here is the source code for playground.gregor.vis.CASimVisClient.java

Source

/* *********************************************************************** *
 * project: org.matsim.*
 *                                                                         *
 * *********************************************************************** *
 *                                                                         *
 * copyright       : (C) 2014 by the members listed in the COPYING,        *
 *                   LICENSE and WARRANTY file.                            *
 * email           : info at matsim dot org                                *
 *                                                                         *
 * *********************************************************************** *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *   See also COPYING, LICENSE and WARRANTY file                           *
 *                                                                         *
 * *********************************************************************** */

package playground.gregor.vis;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.gicentre.utils.move.ZoomPan;
import org.matsim.core.gbl.MatsimRandom;

import playground.gregor.casim.simulation.physics.AbstractCANetwork;
import playground.gregor.proto.ProtoFrame;
import playground.gregor.proto.ProtoFrame.CtrlMsg;
import playground.gregor.proto.ProtoFrame.CtrlMsgRsp;
import playground.gregor.proto.ProtoFrame.Frame;
import playground.gregor.proto.ProtoFrame.Frame.Event;
import playground.gregor.proto.ProtoFrame.Frame.Event.Type;
import playground.gregor.proto.ProtoFrame.FrameRqst;
import playground.gregor.proto.ProtoFrame.FrameServerService.BlockingInterface;
import playground.gregor.proto.ProtoScenario.Scenario;
import playground.gregor.proto.ProtoScenario.Scenario.Network.Link;
import playground.gregor.proto.ProtoScenario.Scenario.Network.Node;
import playground.gregor.proto.ProtoScenario.ScnReq;
import playground.gregor.sim2d_v4.debugger.eventsbaseddebugger.Control;
import playground.gregor.vis.drawing.EventsBasedVisDebugger;
import playground.gregor.vis.drawing.InfoBox;
import processing.core.PVector;

import com.google.protobuf.RpcController;
import com.google.protobuf.ServiceException;
import com.googlecode.protobuf.pro.duplex.PeerInfo;
import com.googlecode.protobuf.pro.duplex.RpcClientChannel;
import com.googlecode.protobuf.pro.duplex.client.DuplexTcpClientPipelineFactory;
import com.googlecode.protobuf.pro.duplex.execute.RpcServerCallExecutor;
import com.googlecode.protobuf.pro.duplex.execute.ThreadPoolCallExecutor;

public class CASimVisClient {
    private static Logger log = Logger.getLogger(CASimVisClient.class);
    private BlockingInterface visService;
    private RpcController cntr;
    private EventsBasedVisDebugger drawer;

    private final Map<String, CircleProperty> circProps = new HashMap<>();
    private final Map<String, LinkInfo> linkInfos = new HashMap<>();
    private final CircleProperty defaultCp = new CircleProperty();
    private long lastUpdate;
    private Control keyControl;
    private double dT = 1. / 25;

    private final String id = MatsimRandom.getRandom().nextDouble() + ""; // TODO
    // create
    // unique
    // id

    public CASimVisClient(BlockingInterface visService, RpcController cntr) {
        this.visService = visService;
        this.cntr = cntr;
    }

    private void init() {
        this.defaultCp.a = 255;
        this.defaultCp.minScale = 0;
        this.defaultCp.rr = .19f;

        this.keyControl = new Control(this.drawer.zoomer, 90, null);
        this.drawer.addKeyControl(this.keyControl);
    }

    private void run() {

        try {
            CtrlMsg regReq = CtrlMsg.newBuilder().setCtrlMsgTyp(CtrlMsg.Type.REGISTER).setId(id).build();
            CtrlMsgRsp regRsp = visService.ctrl(cntr, regReq);

            ScnReq scReq = ScnReq.newBuilder().build();
            Scenario scRsp = visService.reqScn(cntr, scReq);
            this.drawer = new EventsBasedVisDebugger(scRsp, null);
            this.drawer.addAdditionalDrawer(new InfoBox());

            init();
            ZoomPan zoomer = this.drawer.zoomer;
            int w = this.drawer.getWidth();
            int h = this.drawer.getHeight();
            PVector br = new PVector(w, h);
            PVector tl = new PVector(0, 0);

            loadScenario(scRsp);

            // log.info(rsp);
            while (true) {

                PVector brC = zoomer.getDispToCoord(br);
                PVector tlC = zoomer.getDispToCoord(tl);

                FrameRqst frReq = FrameRqst.newBuilder().setTlX(tlC.x - drawer.getOffsetX() - 100)
                        .setTlY(-(drawer.getOffsetY() + tlC.y) + 100).setBrX(brC.x - drawer.getOffsetX() + 100)
                        .setBrY(-(drawer.getOffsetY() + brC.y) - 100).setTime(0).setId(id).build();
                Frame frame = visService.reqFrame(cntr, frReq);
                handleFrame(frame);
            }

        } catch (ServiceException e) {
            throw new RuntimeException(e);
        }
    }

    private void loadScenario(Scenario scRsp) {
        Map<String, Node> nodes = new HashMap<>();
        for (Node n : scRsp.getNet().getNodesList()) {
            nodes.put(n.getId(), n);
        }
        Set<String> handled = new HashSet<>();
        for (Link l : scRsp.getNet().getLinksList()) {

            Node from = nodes.get(l.getFromNodeId());
            Node to = nodes.get(l.getToNodeId());
            StringBuffer b1 = new StringBuffer();
            StringBuffer b2 = new StringBuffer();
            b1.append(from.getId());
            b1.append('_');
            b1.append(to.getId());
            String id = b1.toString();
            b2.append(to.getId());
            b2.append('_');
            b2.append(from.getId());
            String refId = b2.toString();

            LinkInfo i = new LinkInfo();
            i.x0 = from.getX();
            i.y0 = from.getY();
            i.x1 = to.getX();
            i.y1 = to.getY();
            i.width = l.getCapacity() * 3;
            // LinkInfoPoly p = new LinkInfoPoly();
            // double dx = (to.getX() - from.getX());
            // double dy = (to.getY() - from.getY());
            // double length = Math.sqrt(dx * dx + dy * dy);
            // dx /= length;
            // dy /= length;
            // double x0 = from.getX() - dy * l.getCapacity() / 2;
            // double y0 = from.getY() + dx * l.getCapacity() / 2;
            // double x1 = from.getX() + dy * l.getCapacity() / 2;
            // double y1 = from.getY() - dx * l.getCapacity() / 2;
            // double x2 = to.getX() + dy * l.getCapacity() / 2;
            // double y2 = to.getY() - dx * l.getCapacity() / 2;
            // double x3 = to.getX() - dy * l.getCapacity() / 2;
            // double y3 = to.getY() + dx * l.getCapacity() / 2;
            // p.x = new double[] { x0, x1, x2, x3, x0 };
            // p.y = new double[] { y0, y1, y2, y3, y0 };
            //
            double area = l.getLength() * l.getCapacity();
            i.area = area;
            //
            // this.linkPolys.put(l.getId(), p);
            this.linkInfos.put(l.getId(), i);
            if (handled.contains(refId)) {
                continue;
            }
            handled.add(id);

            this.drawer.addLineStatic(from.getX(), from.getY(), to.getX(), to.getY(), 192, 192, 192, 255, 0,
                    3 * l.getCapacity());

        }

    }

    private void handleFrame(Frame frame) {
        for (Event e : frame.getEvntList()) {
            if (e.getEvntType() == Type.POS) {
                handlePosEvent(e);
            } else if (e.getEvntType() == Type.LINK_INF) {
                handleLinkInfEvent(e);
            }
        }
        update(frame.getTime());

    }

    private void update(double time) {
        this.keyControl.awaitPause();
        this.keyControl.awaitScreenshot();
        this.keyControl.update(time);
        long timel = System.currentTimeMillis();

        long last = this.lastUpdate;
        long diff = timel - last;
        if (diff < this.dT * 1000 / this.keyControl.getSpeedup()) {
            long wait = (long) (this.dT * 1000 / this.keyControl.getSpeedup() - diff);
            try {
                Thread.sleep(wait);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.drawer.update(time);
        this.lastUpdate = System.currentTimeMillis();

    }

    private void handlePosEvent(Event event) {
        double dx = event.getVy();
        double dy = -event.getVx();
        double length = Math.sqrt(dx * dx + dy * dy);
        dx /= length;
        dy /= length;
        double x0 = event.getX() + event.getVx();
        double y0 = event.getY() + event.getVy();
        double al = .20;
        double x1 = x0 + dy * al - dx * al / 4;
        double y1 = y0 - dx * al - dy * al / 4;
        double x2 = x0 + dy * al + dx * al / 4;
        double y2 = y0 - dx * al + dy * al / 4;
        double z = this.drawer.zoomer.getZoomScale();
        int a = 255;
        if (z >= 48 && z < 80) {
            z -= 48;
            a = (int) (255. / 32 * z + .5);
        }
        this.drawer.addLine(event.getX(), event.getY(), event.getX() + event.getVx() + dy * al,
                event.getY() + event.getVy() - dx * al, 0, 0, 0, a, 50);
        this.drawer.addTriangle(x0, y0, x1, y1, x2, y2, 0, 0, 0, a, 50, true);

        CircleProperty cp = this.circProps.get(event.getId());
        if (cp == null) {
            cp = createAndAddCircleProperty(event);

        }

        this.drawer.addCircle(event.getX(), event.getY(), cp.rr, cp.r, cp.g, cp.b, cp.a, cp.minScale, cp.fill);
        this.drawer.addText(event.getX(), event.getY(), event.getId(), 300);
    }

    private CircleProperty createAndAddCircleProperty(Event event) {
        CircleProperty cp = new CircleProperty();
        cp.rr = (float) Math.sqrt((1 / AbstractCANetwork.RHO_HAT) / Math.PI);
        int nr = event.getId().hashCode() % 100;
        int color = (nr / 10) % 3;
        // if (Integer.parseInt(a.getId().toString()) < 0) {
        // color = 1;
        // } else {
        // color = 2;
        // }
        if (color == 1) {
            cp.r = 255;
            cp.g = 255 - nr;
            cp.b = 0;
            cp.a = 255;
        } else if (color == 2) {
            cp.r = nr - nr;
            cp.g = 0;
            cp.b = 255;
            cp.a = 255;
        } else {
            cp.r = 0;
            cp.g = 255;
            cp.b = 255 - nr;
            cp.a = 255;
        }
        this.circProps.put(event.getId(), cp);
        return cp;
    }

    private void handleLinkInfEvent(Event e) {
        LinkInfo i = this.linkInfos.get(e.getId());
        double density = e.getNrAgents() / i.area;
        int r, g, b;
        if (density < 1) {
            r = 0;
            g = 255;
            b = 0;
        } else if (density < 1.5) {
            r = 255;
            g = 255;
            b = 0;
        } else if (density < 2) {
            r = 255;
            g = 64;
            b = 0;
        } else if (density < 4) {
            r = 255;
            g = 0;
            b = 0;
        } else {
            r = 128;
            g = 0;
            b = 128;
        }
        // this.drawer.addPolygon(p.x, p.y, r, g, b, 255, 0);
        this.drawer.addLine(i.x0, i.y0, i.x1, i.y1, r, g, b, 255, 0, i.width);

    }

    public static void main(String[] args) throws Exception {
        if (args.length != 2) {
            System.out.println("usage: VisClient <server> <port>");
            System.exit(-1);
        }
        String serv = args[0];
        int port = Integer.parseInt(args[1]);

        PeerInfo server = new PeerInfo(serv, port);
        DuplexTcpClientPipelineFactory clientFactory = new DuplexTcpClientPipelineFactory();

        // in case client acts as server, which is the reason behind a duplex
        // connection indeed.
        RpcServerCallExecutor executor = new ThreadPoolCallExecutor(3, 100);
        clientFactory.setRpcServerCallExecutor(executor);

        clientFactory.setConnectResponseTimeoutMillis(1000);

        // clientFactory.getRpcServiceRegistry().registerService();

        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(new NioEventLoopGroup());
        bootstrap.handler(clientFactory);
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.option(ChannelOption.TCP_NODELAY, true);
        bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
        bootstrap.option(ChannelOption.SO_SNDBUF, 1048576);
        bootstrap.option(ChannelOption.SO_RCVBUF, 1048576);

        RpcClientChannel channel = clientFactory.peerWith(server, bootstrap);

        BlockingInterface visService = ProtoFrame.FrameServerService.newBlockingStub(channel);
        RpcController cntr = channel.newRpcController();
        clientFactory.getRpcServiceRegistry().registerService(
                ProtoFrame.FrameServerService.newReflectiveBlockingService(new BlockingVisServiceImpl(null, null)));

        new CASimVisClient(visService, cntr).run();
        //
        // channel.close();
        // executor.shutdown();
        // System.exit(0);
    }

    private static final class CircleProperty {
        boolean fill = true;
        float rr;
        int r, g, b, a, minScale = 0;
    }

    private static final class LinkInfoPoly {
        double[] x;
        double[] y;
        double area;
    }

    private static final class LinkInfo {
        public double area;
        double x0;
        double x1;
        double y0;
        double y1;
        double width;
    }
}