/*
* JaamSim Discrete Event Simulation
* Copyright (C) 2013 Ausenco Engineering Canada Inc.
*
* 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.jaamsim.DisplayModels;
import java.util.ArrayList;
import java.util.List;
import com.jaamsim.Graphics.DisplayEntity;
import com.jaamsim.Graphics.PolylineInfo;
import com.jaamsim.basicsim.Entity;
import com.jaamsim.controllers.RenderManager;
import com.jaamsim.input.ColourInput;
import com.jaamsim.math.Color4d;
import com.jaamsim.math.Transform;
import com.jaamsim.math.Vec3d;
import com.jaamsim.math.Vec4d;
import com.jaamsim.render.DisplayModelBinding;
import com.jaamsim.render.LineProxy;
import com.jaamsim.render.PointProxy;
import com.jaamsim.render.RenderProxy;
import com.jaamsim.render.RenderUtils;
import com.jaamsim.render.VisibilityInfo;
public class PolylineModel extends DisplayModel {
private static final Color4d MINT = ColourInput.getColorWithName("mint");
@Override
public DisplayModelBinding getBinding(Entity ent) {
return new Binding(ent, this);
}
@Override
public boolean canDisplayEntity(Entity ent) {
return (ent instanceof DisplayEntity);
}
protected class Binding extends DisplayModelBinding {
//private Segment _segmentObservee;
protected DisplayEntity displayObservee;
private PolylineInfo[] pisCache;
private Transform transCache;
private VisibilityInfo viCache;
protected ArrayList<Vec4d> selectionPoints = null;
private ArrayList<Vec4d> nodePoints = null;
private LineProxy[] cachedProxies = null;
public Binding(Entity ent, DisplayModel dm) {
super(ent, dm);
try {
displayObservee = (DisplayEntity)ent;
} catch (ClassCastException e) {
// The observee is not a display entity
displayObservee = null;
}
}
/**
* Update the cached Points list
*/
protected void updateProxies(double simTime) {
PolylineInfo[] pis = displayObservee.getScreenPoints(simTime);
if (pis == null || pis.length == 0)
return;
Transform trans = null;
if (displayObservee.getCurrentRegion() != null || displayObservee.getRelativeEntity() != null) {
trans = displayObservee.getGlobalPositionTransform();
}
VisibilityInfo vi = getVisibilityInfo();
boolean dirty = false;
dirty = dirty || !compareArray(pisCache, pis);
dirty = dirty || !compare(transCache, trans);
dirty = dirty || !compare(viCache, vi);
pisCache = pis;
transCache = trans;
viCache = vi;
if (cachedProxies != null && !dirty) {
// up to date
registerCacheHit("Points");
return;
}
registerCacheMiss("Points");
selectionPoints = new ArrayList<>();
nodePoints = new ArrayList<>();
// Cache the points in the first series for selection and editing
ArrayList<Vec3d> basePoints = pis[0].getPoints();
if (basePoints == null || basePoints.size() < 2) {
cachedProxies = new LineProxy[0];
return;
}
for (int i = 1; i < basePoints.size(); ++i) { // Skip the first point
Vec3d start = basePoints.get(i - 1);
Vec3d end = basePoints.get(i);
selectionPoints.add(new Vec4d(start.x, start.y, start.z, 1.0d));
selectionPoints.add(new Vec4d(end.x, end.y, end.z, 1.0d));
}
for (int i = 0; i < basePoints.size(); ++i) {
// Save the point list as is for control nodes
Vec3d p = basePoints.get(i);
nodePoints.add(new Vec4d(p.x, p.y, p.z, 1.0d));
}
if (trans != null) {
RenderUtils.transformPointsLocal(trans, selectionPoints, 0);
RenderUtils.transformPointsLocal(trans, nodePoints, 0);
}
// Add the line proxies
cachedProxies = new LineProxy[pis.length];
int proxyIndex = 0;
for (PolylineInfo pi : pis) {
List<Vec4d> points = new ArrayList<>();
ArrayList<Vec3d> curvePoints = pi.getCurvePoints();
for (int i = 1; i < curvePoints.size(); ++i) { // Skip the first point
Vec3d start = curvePoints.get(i - 1);
Vec3d end = curvePoints.get(i);
points.add(new Vec4d(start.x, start.y, start.z, 1.0d));
points.add(new Vec4d(end.x, end.y, end.z, 1.0d));
}
if (trans != null) {
RenderUtils.transformPointsLocal(trans, points, 0);
}
cachedProxies[proxyIndex++] = new LineProxy(points, pi.getColor(), pi.getWidth(), vi, displayObservee.getEntityNumber());
}
}
@Override
public void collectProxies(double simTime, ArrayList<RenderProxy> out) {
if (displayObservee == null ||!displayObservee.getShow()) {
return;
}
updateProxies(simTime);
for (LineProxy lp : cachedProxies) {
out.add(lp);
}
}
@Override
public void collectSelectionProxies(double simTime, ArrayList<RenderProxy> out) {
if (displayObservee == null ||
!displayObservee.getShow() ||
!displayObservee.selectable()) {
return;
}
updateProxies(simTime);
if (selectionPoints.size() == 0) {
return;
}
LineProxy lp = new LineProxy(selectionPoints, MINT, 2, getVisibilityInfo(), RenderManager.LINEDRAG_PICK_ID);
lp.setHoverColour(ColourInput.LIGHT_GREY);
out.add(lp);
for (int i = 0; i < nodePoints.size(); ++i) {
Color4d col = ColourInput.GREEN;
if (i == 0)
col = ColourInput.BLUE;
if (i == nodePoints.size() -1)
col = ColourInput.YELLOW;
addPoint(nodePoints.get(i), col, ColourInput.LIGHT_GREY, RenderManager.LINENODE_PICK_ID - i, out);
}
}
}
private void addPoint(Vec4d p, Color4d col, Color4d hovCol, long pickID, ArrayList<RenderProxy> out) {
List<Vec4d> pl = new ArrayList<>(1);
pl.add(new Vec4d(p));
PointProxy pp = new PointProxy(pl, col, 8, getVisibilityInfo(), pickID);
pp.setHoverColour(hovCol);
pp.setCollisionAngle(0.004363); // 0.25 degrees in radians
out.add(pp);
}
}