2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2013 - Pedro Arthur dos S. Souza
4 * Copyright (C) 2013 - Caio Lucas dos S. Souza
6 * Copyright (C) 2012 - 2016 - Scilab Enterprises
8 * This file is hereby licensed under the terms of the GNU GPL v2.0,
9 * pursuant to article 5.3.4 of the CeCILL v.2.1.
10 * This file was originally licensed under the terms of the CeCILL v2.1,
11 * and continues to be available under such terms.
12 * For more information, see the COPYING file which you should have received
13 * along with this program.
17 package org.scilab.modules.gui.editor;
20 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
21 import org.scilab.modules.graphic_objects.graphicObject.GraphicObject;
22 import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
23 import org.scilab.modules.graphic_objects.CallGraphicController;
24 import org.scilab.modules.renderer.CallRenderer;
26 import org.scilab.modules.graphic_objects.axes.Axes;
27 import org.scilab.modules.renderer.JoGLView.axes.AxesDrawer;
28 import org.scilab.modules.renderer.JoGLView.DrawerVisitor;
29 import org.scilab.forge.scirenderer.tranformations.Vector3d;
31 import org.scilab.modules.graphic_objects.PolylineData;
32 import org.scilab.modules.graphic_objects.SurfaceData;
33 import org.scilab.modules.graphic_objects.ObjectData;
34 import org.scilab.modules.renderer.utils.CommonHandler;
35 import org.scilab.modules.renderer.utils.AxesHandler;
37 import java.lang.Math;
38 import java.util.List;
39 import java.util.LinkedList;
42 * GED Object picker for all Graphics Objects
45 public class GEDPicker {
47 private final Double delta = 7.0;
48 private Integer axesUID;
53 * Picker, given a figure and a click position in pixel coordinates
54 * it returns an array of objects picked
56 * @param figureUID Unique id from the figure object
57 * @param position Mouse click position in pixels
58 * @return Array of picked objects
60 public Integer[] pick(Integer figureUID, Integer[] position) {
63 boolean curObj = false;
65 axesUID = AxesHandler.clickedAxes(figureUID, position);
66 axes = AxesHandler.getAxesFromUid(axesUID);
69 return new Integer[] { figureUID };
71 List<Integer> ret = new LinkedList<Integer>();
72 AllObjs = getAllObjAsArray(axesUID);
74 for (int i = 0; i < AllObjs.length; i++) {
76 Integer type = (Integer)GraphicController.getController().getProperty(AllObjs[i], GraphicObjectProperties.__GO_TYPE__);
77 if (!CommonHandler.isVisible(AllObjs[i])) {
82 case GraphicObjectProperties.__GO_POLYLINE__:
83 curObj = getPolyline(AllObjs[i], position);
85 case GraphicObjectProperties.__GO_PLOT3D__:
86 case GraphicObjectProperties.__GO_GRAYPLOT__:
87 case GraphicObjectProperties.__GO_FAC3D__:
88 case GraphicObjectProperties.__GO_MATPLOT__:
89 curObj = getSurface(AllObjs[i], position);
91 case GraphicObjectProperties.__GO_LEGEND__:
92 curObj = getLegend(AllObjs[i], position);
94 case GraphicObjectProperties.__GO_LABEL__:
95 curObj = getLabel(AllObjs[i], position);
97 case GraphicObjectProperties.__GO_ARC__:
98 curObj = getArc(AllObjs[i], position);
100 case GraphicObjectProperties.__GO_CHAMP__:
101 curObj = getChamp(AllObjs[i], position);
103 case GraphicObjectProperties.__GO_FEC__:
104 curObj = getFec(AllObjs[i], position);
106 case GraphicObjectProperties.__GO_RECTANGLE__:
107 curObj = getRectangle(AllObjs[i], position);
109 case GraphicObjectProperties.__GO_SEGS__:
110 curObj = getSegs(AllObjs[i], position);
112 case GraphicObjectProperties.__GO_DATATIP__:
113 curObj = getDatatip(AllObjs[i], position);
115 case GraphicObjectProperties.__GO_COMPOUND__:
123 if (ret.size() > 0) {
124 return ret.toArray(new Integer[ret.size()]);
127 if (isInsideAxes(figureUID, position)) {
128 return new Integer[] { axesUID };
130 return new Integer[] { figureUID };
135 * Polyline picker, given a polyline object it checks if the click
138 * @param obj The given polyline object uid
139 * @param position Mouse click position in pixels
140 * @return true if picked the polyline otherwise returns false
142 boolean getPolyline(Integer obj, Integer[] position) {
144 double[] datax = (double[])PolylineData.getDataX(obj);
145 double[] datay = (double[])PolylineData.getDataY(obj);
146 double[] dataz = (double[])PolylineData.getDataZ(obj);
148 if (PolylineData.isXShiftSet(obj) != 0) {
149 double[] x_shift = (double[])PolylineData.getShiftX(obj);
150 for (int i = 0; i < datax.length; ++i) {
151 datax[i] += x_shift[i];
155 if (PolylineData.isYShiftSet(obj) != 0) {
156 double[] y_shift = (double[])PolylineData.getShiftY(obj);
157 for (int i = 0; i < datay.length; ++i) {
158 datay[i] += y_shift[i];
162 if (PolylineData.isZShiftSet(obj) != 0) {
163 double[] z_shift = (double[])PolylineData.getShiftZ(obj);
164 for (int i = 0; i < dataz.length; ++i) {
165 dataz[i] += z_shift[i];
169 datax = CommonHandler.toLogScale(datax, axes.getXAxisLogFlag());
170 datay = CommonHandler.toLogScale(datay, axes.getYAxisLogFlag());
171 dataz = CommonHandler.toLogScale(dataz, axes.getZAxisLogFlag());
174 double[] pos = {1.0 * position[0], 1.0 * position[1], 1.0};
175 double[] c2d = CallRenderer.get2dViewFromPixelCoordinates(axesUID, pos);
179 double[] c2d2 = CallRenderer.get2dViewFromPixelCoordinates(axesUID, pos);
181 double dx = Math.abs(c2d[0] - c2d2[0]);
182 double dy = Math.abs(c2d[1] - c2d2[1]);
184 if (AxesHandler.isZoomBoxEnabled(axesUID)) {
185 if (!AxesHandler.isInZoomBoxBounds(axesUID, c2d[0], c2d[1])) {
190 Double[] rotAngles = (Double[])GraphicController.getController().getProperty(axesUID, GraphicObjectProperties.__GO_ROTATION_ANGLES__);
191 boolean default2dView = (rotAngles[0] == 0.0 && rotAngles[1] == 270.0);
192 double[] oldPoint = new double[3];
194 if (CommonHandler.isLineEnabled(obj)) {
195 //System.out.println("lineEnable");
196 if (!default2dView) {
197 oldPoint = AxesDrawer.compute2dViewCoordinates(axes, new double[] { datax[0], datay[0], dataz[0] });
198 //System.out.println("NotDefault");
201 for (Integer i = 0; i < (datax.length - 1); ++i) {
202 if (!default2dView) {
203 double[] newPoint = AxesDrawer.compute2dViewCoordinates(axes, new double[] {datax[i + 1], datay[i + 1], dataz[i + 1]});
204 if (isInRange(oldPoint[0], newPoint[0], oldPoint[1], newPoint[1], c2d[0], c2d[1], dx, dy)) {
205 //System.out.println("in");
210 if (isInRange(datax[i], datax[i + 1], datay[i], datay[i + 1], c2d[0], c2d[1], dx, dy)) {
217 if (CommonHandler.isMarkEnabled(obj)) {
219 Integer markSize = CommonHandler.getMarkSize(obj);
220 Integer unit = CommonHandler.getMarkSizeUnit(obj);
222 int finalSize = (unit == 1) ? (8 + 2 * markSize) : markSize;
224 double deltax = Math.abs((dx / delta) * finalSize);
225 double deltay = Math.abs((dy / delta) * finalSize);
228 for (int i = 0; i < datax.length; ++i) {
229 if (!default2dView) {
230 double[] point = AxesDrawer.compute2dViewCoordinates(axes, new double[] {datax[i], datay[i], dataz[i]});
231 if ((Math.abs(point[0] - c2d[0]) <= deltax) && (Math.abs(point[1] - c2d[1]) <= deltay)) {
235 if ((Math.abs(datax[i] - c2d[0]) <= deltax) && (Math.abs(datay[i] - c2d[1]) <= deltay)) {
246 * Surface picker, given a plot3d/fac3d/grayplot/matplot object it checks if the click
249 * @param obj The given surface object uid
250 * @param position Mouse click position in pixels
251 * @return true if picked the surface otherwise returns false
253 boolean getSurface(Integer obj, Integer[] position) {
254 GraphicObject go = GraphicController.getController().getObjectFromId(obj);
255 Integer figure = go.getParentFrameOrFigure();
256 double[] mat = DrawerVisitor.getVisitor(figure).getAxesDrawer().getProjection(axesUID).getMatrix();
257 double[][] factors = axes.getScaleTranslateFactors();
259 Vector3d v0 = AxesDrawer.unProject(axes, new Vector3d(1.0f * position[0], 1.0f * position[1], 0.0));
260 Vector3d v1 = AxesDrawer.unProject(axes, new Vector3d(1.0f * position[0], 1.0f * position[1], 1.0));
261 v0 = new Vector3d((v0.getX() - factors[1][0]) / factors[0][0], (v0.getY() - factors[1][1]) / factors[0][1], (v0.getZ() - factors[1][2]) / factors[0][2]);
262 v1 = new Vector3d((v1.getX() - factors[1][0]) / factors[0][0], (v1.getY() - factors[1][1]) / factors[0][1], (v1.getZ() - factors[1][2]) / factors[0][2]);
264 Vector3d Dir = v0.minus(v1).getNormalized();
265 // ray is the parametric cuve t -> v0 + t * Dir
267 double t = SurfaceData.pickSurface(obj, v0.getX(), v0.getY(), v0.getZ(), Dir.getX(), Dir.getY(), Dir.getZ());
269 if (t != Double.NEGATIVE_INFINITY) {
270 Vector3d intersectPoint = new Vector3d(v0.plus(Dir.times(t)));
271 double curZ = intersectPoint.getX() * mat[2] + intersectPoint.getY() * mat[6] + intersectPoint.getZ() * mat[10] + mat[14];
280 * Legend picker, given a legend object it checks if the click
283 * @param obj The given legend object uid
284 * @param position Mouse click position in pixels
285 * @return true if picked the legend otherwise returns false
287 boolean getLegend(Integer obj, Integer[] position) {
288 Integer[] axesSize = {0, 0};
290 Double[] axesBounds = { 0., 0. }, dPosition = { 0., 0. }, legendPos = { 0., 0. }, legendBounds = { 0., 0., 0., 0. }, dimension = { 0., 0. };
292 GraphicObject go = GraphicController.getController().getObjectFromId(obj);
293 Integer figure = go.getParentFrameOrFigure();
294 axesSize = (Integer[])GraphicController.getController().getProperty(figure, GraphicObjectProperties.__GO_AXES_SIZE__);
295 axesBounds = (Double[])GraphicController.getController().getProperty(axesUID, GraphicObjectProperties.__GO_AXES_BOUNDS__);
296 legendPos = (Double[])GraphicController.getController().getProperty(obj, GraphicObjectProperties.__GO_POSITION__);
297 dPosition[0] = (position[0] - (axesBounds[0] * axesSize[0])) / (axesBounds[2] * axesSize[0]);
298 dPosition[1] = (position[1] - (axesBounds[1] * axesSize[1])) / (axesBounds[3] * axesSize[1]);
299 dimension = (Double[])GraphicController.getController().getProperty(obj, GraphicObjectProperties.__GO_SIZE__);
300 legendBounds[0] = legendPos[0];
301 legendBounds[1] = legendPos[1];
302 legendBounds[2] = legendPos[0] + dimension[0];
303 legendBounds[3] = legendPos[1] + dimension[1];
305 if (dPosition[0] >= legendBounds[0] && dPosition[0] <= legendBounds[2] && dPosition[1] >= legendBounds[1] && dPosition[1] <= legendBounds[3]) {
312 * Label picker, given a label object it checks if the click
315 * @param obj The given surface object uid
316 * @param position Mouse click position in pixels
317 * @return true if picked the surface otherwise returns false
319 boolean getLabel(Integer obj, Integer[] position) {
321 Double[] corners = (Double[])GraphicController.getController().getProperty(obj, GraphicObjectProperties.__GO_CORNERS__);
322 Double radAngle = (Double)GraphicController.getController().getProperty(obj, GraphicObjectProperties.__GO_FONT_ANGLE__);
323 int rotate = ((int)((radAngle * 2) / Math.PI)) % 2;
326 Double[] temp = new Double[corners.length];
327 for (Integer i = 0; i < corners.length - 3; i++) {
328 temp[i + 3] = corners[i];
330 temp[0] = corners[corners.length - 3];
331 temp[1] = corners[corners.length - 2];
332 temp[2] = corners[corners.length - 1];
335 double[] point = new double[] { 1.0 * position[0], 1.0 * position[1], 1.0};
336 double[] coord = CallRenderer.get2dViewFromPixelCoordinates(axesUID, point);
337 boolean[] logScale = { (Boolean)GraphicController.getController().getProperty(axesUID, GraphicObjectProperties.__GO_X_AXIS_LOG_FLAG__),
338 (Boolean)GraphicController.getController().getProperty(axesUID, GraphicObjectProperties.__GO_Y_AXIS_LOG_FLAG__)
340 coord[0] = CommonHandler.InverseLogScale(coord[0], logScale[0]);
341 coord[1] = CommonHandler.InverseLogScale(coord[1], logScale[1]);
343 if ((coord[0] >= corners[0] && coord[0] <= corners[6]) || (coord[0] <= corners[0] && coord[0] >= corners[6])) {
344 if ((coord[1] >= corners[1] && coord[1] <= corners[4]) || (coord[1] <= corners[1] && coord[1] >= corners[4])) {
352 * Arc picker, given a arc object it checks if the click
355 * @param obj The given arc object uid
356 * @param position Mouse click position in pixels
357 * @return true if picked the arc otherwise returns false
359 boolean getArc(Integer obj, Integer[] position) {
361 double[] upperLeft = (double[])ObjectData.getArcUpperLeftPoint(obj);
362 double[] data = (double[])ObjectData.getArcData(obj);
363 double[] pos = { position[0] * 1.0, position[1] * 1.0, 0.0 };
364 double[] c2d = CallRenderer.get2dViewFromPixelCoordinates(axesUID, pos);
367 double[] c2d2 = CallRenderer.get2dViewFromPixelCoordinates(axesUID, pos);
368 Boolean fill_mode = (Boolean)GraphicController.getController().getProperty(obj, GraphicObjectProperties.__GO_FILL_MODE__);
370 //Calculates the selection delta based on ellipse & axes size
371 double dt = Math.sqrt(Math.pow(c2d[0] - c2d2[0], 2.0) + Math.pow(c2d[1] - c2d2[1], 2.0)) / Math.sqrt((data[0] * data[0] / 4.) / 2. + (data[1] * data[1] / 4.) / 2.);
373 double[] c3d1 = AxesDrawer.compute3dViewCoordinates(axes, c2d);
375 double[] c3d2 = AxesDrawer.compute3dViewCoordinates(axes, c2d);
377 //Calculates the intersection of the click ray with the ellipse plane
378 Vector3d v0 = new Vector3d(c3d1);
379 Vector3d v1 = new Vector3d(c3d2);
380 Vector3d dir = v1.minus(v0);
382 if (dir.getZ() == 0) {
386 double u = (upperLeft[2] - v0.getZ()) / dir.getZ();
387 Vector3d point = v0.plus(dir.times(u));
389 double xr = data[1] / 2.;
390 double yr = data[0] / 2.;
392 Vector3d center = new Vector3d(upperLeft[0] + xr, upperLeft[1] - yr, upperLeft[2]);
394 //checks if the point lies within the ellipse
395 double x = point.getX() - center.getX();
396 double y = point.getY() - center.getY();
397 double v = (x * x) / (xr * xr) + (y * y) / (yr * yr);
403 double angle0 = getAngle360(data[2]);
404 double angle1 = getAngle360(data[3]) + angle0;
407 * Checks if the point is closer to the drawn arc
408 * and inside de given angles. If fill_mode = false
409 * it it accept 1-dt < value < 1+dt, if fill_mode = true
410 * it accept value < 1+dt;
413 v0 = new Vector3d(1.0, 0.0, 0.0);
414 v1 = point.minus(center);
415 double angle = Math.acos(v0.scalar(v1) / (v0.getNorm() * v1.getNorm()));
416 angle += v1.getY() < 0.0 ? Math.PI : 0.0;
418 if (!(angle0 == angle1) && !(angle >= angle0 && angle <= angle1)) {
424 } else if (v > 1.0 - dt) {
431 double getAngle360(double a) {
432 while (a > 2 * Math.PI) {
439 * Champ picker, given a champ object it checks if the click
442 * @param obj The given champ object uid
443 * @param position Mouse click position in pixels
444 * @return true if picked the champ otherwise returns false
446 boolean getChamp(Integer obj, Integer[] position) {
448 double[] datax = (double[])ObjectData.getChampX(obj);
449 double[] datay = (double[])ObjectData.getChampY(obj);
450 double[] data = (double[])ObjectData.getArrows(obj);
453 for (int i = 0; i < data.length; i++) {
454 scale = data[i] > scale ? data[i] : scale;
457 double[][] arrows = getAsStdMatrix(data, scale);
458 if (arrows == null) {
461 double[] pos = {1.0 * position[0], 1.0 * position[1], 1.0};
463 double[] c2d = CallRenderer.get2dViewFromPixelCoordinates(axesUID, pos);
466 double[] c2d2 = CallRenderer.get2dViewFromPixelCoordinates(axesUID, pos);
468 double dx = Math.abs(c2d[0] - c2d2[0]);
469 double dy = Math.abs(c2d[1] - c2d2[1]);
470 int xSize = datax.length;
471 int ySize = datay.length;
473 for (int i = 0; i < xSize; i++) {
474 for (int j = 0; j < ySize; j++) {
476 double[] ch2d = AxesDrawer.compute2dViewCoordinates(axes, new double[] { datax[i], datay[j], 0.0});
477 double[] temp = { datax[i] + arrows[i * xSize + j][0], datay[j] + arrows[i * xSize + j][1], arrows[i * xSize + j][2]};
478 double[] ch2d2 = AxesDrawer.compute2dViewCoordinates(axes, temp);
479 if (isInRange(ch2d[0], ch2d2[0], ch2d[1], ch2d2[1], c2d[0], c2d[1], dx, dy)) {
482 if ((Math.abs(c2d[0] - ch2d[0]) <= dx) && (Math.abs(c2d[1] - ch2d[1]) <= dy)) {
485 if ((Math.abs(c2d[0] - ch2d2[0]) <= dx) && (Math.abs(c2d[1] - ch2d2[1]) <= dy)) {
494 * Fec picker, given a fec object it checks if the click
497 * @param obj The given fec object uid
498 * @param position Mouse click position in pixels
499 * @return true if picked the fec otherwise returns false
501 boolean getFec(Integer obj, Integer[] position) {
502 int numVerticesByElem = ObjectData.getFecNumVerticesByElement(obj);
503 double[] elements = (double[])ObjectData.getFecElements(obj);
504 double[] data = (double[])ObjectData.getFecData(obj);
506 double[] pos = { position[0] * 1.0, position[1] * 1.0, 0.0 };
507 double[] c2d = CallRenderer.get2dViewFromPixelCoordinates(axesUID, pos);
508 double[] c3d1 = AxesDrawer.compute3dViewCoordinates(axes, c2d);
511 double[] c3d2 = AxesDrawer.compute3dViewCoordinates(axes, c2d);
512 Vector3d l0 = new Vector3d(c3d1);
513 Vector3d l1 = new Vector3d(c3d2);
514 Vector3d dir = l1.minus(l0);
515 int idx1, idx2, idx3;
518 int tSize = elements.length / (numVerticesByElem + 2);
519 for (int i = 0; i < tSize; i++) {
520 idx1 = (int)elements[tSize + i];
521 for (int j = 2; j < numVerticesByElem; ++j) {
522 idx2 = (int)elements[j * tSize + i];
523 idx3 = (int)elements[(j + 1) * tSize + i];
525 p1 = new Vector3d(data[(idx1 - 1) * 3], data[(idx1 - 1) * 3 + 1], data[(idx1 - 1) * 3 + 2]);
526 p2 = new Vector3d(data[(idx2 - 1) * 3], data[(idx2 - 1) * 3 + 1], data[(idx2 - 1) * 3 + 2]);
527 p3 = new Vector3d(data[(idx3 - 1) * 3], data[(idx3 - 1) * 3 + 1], data[(idx3 - 1) * 3 + 2]);
529 if (testTri(p1, p2, p3, l0, dir)) {
537 * Möller–Trumbore intersection algorithm
538 * Test if a line intersect a triangle
540 * @param p1 The vertex 1 of the triangle
541 * @param p2 The vertex 2 of the triangle
542 * @param p3 The vertex 3 of the triangle
543 * @param l0 origin point
544 * @param direction The direction vector
545 * @return true if it intersect the triangle, false otherwise
547 private boolean testTri(Vector3d p1, Vector3d p2, Vector3d p3, Vector3d l0, Vector3d direction) {
549 Vector3d e1 = p2.minus(p1);
550 Vector3d e2 = p3.minus(p1);
552 Vector3d h = Vector3d.product(direction, e2);
553 double det = e1.scalar(h);
555 if (det > -0.00001 && det < 0.00001) {
559 double inv = 1.0 / det;
560 Vector3d s = l0.minus(p1);
562 double u = s.scalar(h) * inv;
563 if (u < 0.0 || u > 1.0) {
567 Vector3d q = Vector3d.product(s, e1);
568 double v = direction.scalar(q) * inv;
569 if (v < 0.0 || (u + v) > 1.0) {
577 * Rectangle picker, given a rectangle object it checks if the click
580 * @param obj The given rectangle object uid
581 * @param position Mouse click position in pixels
582 * @return true if picked the rectangle otherwise returns false
584 boolean getRectangle(Integer obj, Integer[] position) {
586 Double[] upperLeft = (Double[])GraphicController.getController().getProperty(obj, GraphicObjectProperties.__GO_UPPER_LEFT_POINT__);
587 Double height = (Double)GraphicController.getController().getProperty(obj, GraphicObjectProperties.__GO_HEIGHT__);
588 Double width = (Double)GraphicController.getController().getProperty(obj, GraphicObjectProperties.__GO_WIDTH__);
589 double[] pos = { position[0] * 1.0, position[1] * 1.0, 0.0 };
590 double[] c2d = CallRenderer.get2dViewFromPixelCoordinates(axesUID, pos);
592 double[] c3d1 = AxesDrawer.compute3dViewCoordinates(axes, c2d);
594 double[] c3d2 = AxesDrawer.compute3dViewCoordinates(axes, c2d);
596 Vector3d v0 = new Vector3d(c3d1);
597 Vector3d v1 = new Vector3d(c3d2);
598 Vector3d c = v1.minus(v0);
604 double u = (upperLeft[2] - v0.getZ()) / c.getZ();
605 Vector3d point = v0.plus(c.times(u));
607 if (point.getX() >= upperLeft[0] && point.getX() <= (upperLeft[0] + width)
608 && point.getY() <= upperLeft[1] && point.getY() >= (upperLeft[1] - height)) {
615 * Segs picker, given a segs object it checks if the click
618 * @param obj The given segs object uid
619 * @param position Mouse click position in pixels
620 * @return true if picked the segs otherwise returns false
622 boolean getSegs(Integer obj, Integer[] position) {
624 double[][] base = getAsStdMatrix((double[])ObjectData.getSegsData(obj), 1.);
625 double[][] arrows = getAsStdMatrix((double[])ObjectData.getArrows(obj), 1.);
627 double[] pos = {1.0 * position[0], 1.0 * position[1], 1.0};
628 double[] c2d = CallRenderer.get2dViewFromPixelCoordinates(axesUID, pos);
631 double[] c2d2 = CallRenderer.get2dViewFromPixelCoordinates(axesUID, pos);
633 double dx = Math.abs(c2d[0] - c2d2[0]);
634 double dy = Math.abs(c2d[1] - c2d2[1]);
635 //System.out.println("Click: " + c2d[0] + "," + c2d[1]);
636 for (int i = 0; i < base.length; i++) {
637 double[] ch2d = AxesDrawer.compute2dViewCoordinates(axes, base[i]);
638 double[] ch2d2 = AxesDrawer.compute2dViewCoordinates(axes, arrows[i]);
639 //System.out.println("P1: " + ch2d[0] + "," + ch2d[1]);
640 //System.out.println("P2: " + ch2d2[0] + "," + ch2d2[1]);
641 if (isInRange(ch2d[0], ch2d2[0], ch2d[1], ch2d2[1], c2d[0], c2d[1], dx, dy)) {
649 * Datatip picker, given a datatip object it checks if the click
652 * @param obj The given datatip object uid
653 * @param position Mouse click position in pixels
654 * @return true if picked the datatip otherwise returns false
656 boolean getDatatip(Integer obj, Integer[] position) {
658 boolean[] logFlags = { axes.getXAxisLogFlag(), axes.getYAxisLogFlag(), axes.getZAxisLogFlag()};
659 double[] pix_pos = {1.0 * position[0], 1.0 * position[1], 1.0};
660 double[] c2d = CallRenderer.get2dViewFromPixelCoordinates(axesUID, pix_pos);
663 double[] c2d2 = CallRenderer.get2dViewFromPixelCoordinates(axesUID, pix_pos);
664 double dx = Math.abs(c2d[0] - c2d2[0]);
665 double dy = Math.abs(c2d[1] - c2d2[1]);
667 Double[] tip_pos = (Double[])GraphicController.getController().getProperty(obj, GraphicObjectProperties.__GO_DATATIP_DATA__);
668 double point[] = new double[3];
669 point[0] = CommonHandler.logScale(tip_pos[0], logFlags[0]);
670 point[1] = CommonHandler.logScale(tip_pos[1], logFlags[1]);
671 point[2] = CommonHandler.logScale(tip_pos[2], logFlags[2]);
673 Double[] rotAngles = (Double[])GraphicController.getController().getProperty(axesUID, GraphicObjectProperties.__GO_ROTATION_ANGLES__);
674 boolean default2dView = (rotAngles[0] == 0.0 && rotAngles[1] == 270.0);
676 if (!default2dView) {
677 point = AxesDrawer.compute2dViewCoordinates(axes, point);
680 Integer size = CommonHandler.getMarkSize(obj);
681 Integer unit = CommonHandler.getMarkSizeUnit(obj);
682 int finalSize = (unit == 1) ? (8 + 2 * size) : size;
685 if ((Math.abs(point[0] - c2d[0]) <= dx * finalSize) && (Math.abs(point[1] - c2d[1]) <= dy * finalSize)) {
689 //TODO: Add selection when the click is inside datatip textbox
694 boolean isInsideAxes(Integer figureUID, Integer[] position) {
695 Double[] rotAngles = (Double[])GraphicController.getController().getProperty(axesUID, GraphicObjectProperties.__GO_ROTATION_ANGLES__);
696 boolean default2dView = (rotAngles[0] == 0.0 && rotAngles[1] == 270.0);
697 // if (default2dView) {
698 Double[] dataBounds = (Double[])GraphicController.getController().getProperty(axesUID, GraphicObjectProperties.__GO_DATA_BOUNDS__);
699 double[] c2d = AxesDrawer.compute2dViewFromPixelCoordinates(axes, new double[] { 1.0 * position[0], 1.0 * position[1], 0.0 });
700 if (c2d[0] >= dataBounds[0] && c2d[0] <= dataBounds[1] && c2d[1] >= dataBounds[2] && c2d[1] <= dataBounds[3]) {
704 //TODO: Add check when it is in 3d view
710 void getObjects(Integer root, List<Integer> putObjs) {
712 Integer count = (Integer)GraphicController.getController().getProperty(root, GraphicObjectProperties.__GO_CHILDREN_COUNT__);
714 Integer[] children = (Integer[])GraphicController.getController().getProperty(root, GraphicObjectProperties.__GO_CHILDREN__);
715 for (int i = 0; i < count; i++) {
716 putObjs.add(children[i]);
717 getObjects(children[i], putObjs);
723 * Given an root object return an array with all children objects
725 * @param root The root object uid
726 * @return Array with all objects
728 Integer[] getAllObjAsArray(Integer root) {
730 List<Integer> objs = new LinkedList<Integer>();
731 getObjects(root, objs);
732 return objs.toArray(new Integer[objs.size()]);
735 private boolean isInRange(Double x0, Double x1, Double y0, Double y1, Double x, Double y, Double xRange, Double yRange) {
736 /* Fast bound check*/
737 double m = (x1 + x0) / 2;
740 double ca = (y1 - y0) / (x1 - x0);
742 double yy = y0 + ca * (x - x0);
744 double pix = xRange / delta;
745 double m_y = (y1 + y0) / 2;
746 double dy = m_y - y0;
748 boolean ca_inf = (Math.abs(x1 - x0) < Math.abs(pix * 2));
749 boolean in_bounds = (Math.abs(m - x) <= Math.abs(pix * 2)) && (Math.abs(m_y - y) <= Math.abs(dy));
752 * test if (x, y) belongs or is closer to the line
753 * if the angular coeficent -> inf(ca_inf), the interpolation fails
754 * then we use "in_bunds" test.
756 return (Math.abs(m - x) <= Math.abs(dx)) && (y >= (yy - yRange)) && (y <= (yy + yRange)) || (ca_inf && in_bounds);
759 private double[][] getAsStdMatrix(double[] data, double scale) {
761 double[][] ret = null;
762 if (data.length % 3 != 0) {
765 ret = new double[data.length / 3][3];
766 for (int i = 0; i < data.length / 3; i++) {
767 for (int j = 0; j < 3; j++) {
768 ret[i][j] = data[i * 3 + j] / scale;