2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010 - DIGITEO - Pierre Lando
4 * Copyright (C) 2011-2012 - DIGITEO - Manuel Juliachs
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
16 #include "DecompositionUtils.hxx"
17 #include "PolylineDecomposer.hxx"
18 #include "Triangulator.hxx"
19 #include "ColorComputer.hxx"
26 #include "getGraphicObjectProperty.h"
27 #include "graphicObjectProperties.h"
30 int PolylineDecomposer::getDataSize(char* id)
33 int *piNPoints = &nPoints;
34 int polylineStyle = 0;
35 int* piPolylineStyle = &polylineStyle;
37 int* piClosed = &closed;
39 getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
40 getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
41 getGraphicObjectProperty(id, __GO_CLOSED__, jni_bool, (void**) &piClosed);
43 /* If 0 points, 0 elements */
50 if (polylineStyle == 1)
55 else if (polylineStyle == 2)
66 /* Vertical segments plus segments */
67 else if (polylineStyle == 3)
71 /* Segments with arrow heads */
72 else if (polylineStyle == 4)
75 /* The numbers of arrow head vertices and indices are exactly the same */
76 nArrowVertices = PolylineDecomposer::getArrowTriangleIndicesSize(nPoints, closed);
78 return nPoints + nArrowVertices;
81 else if (polylineStyle == 5)
85 /* Vertical bars plus segments */
86 else if (polylineStyle == 6)
90 /* Horizontal bars plus segments */
91 else if (polylineStyle == 7)
95 /* To be done: remaining styles */
103 void PolylineDecomposer::fillVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation, int logMask)
106 double* xshift = NULL;
107 double* yshift = NULL;
108 double* zshift = NULL;
110 int polylineStyle = 0;
111 int* piPolylineStyle = &polylineStyle;
114 int *piNPoints = &nPoints;
116 getGraphicObjectProperty(id, __GO_DATA_MODEL_COORDINATES__, jni_double_vector, (void**) &t);
117 getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
119 getGraphicObjectProperty(id, __GO_DATA_MODEL_X_COORDINATES_SHIFT__, jni_double_vector, (void**) &xshift);
120 getGraphicObjectProperty(id, __GO_DATA_MODEL_Y_COORDINATES_SHIFT__, jni_double_vector, (void**) &yshift);
121 getGraphicObjectProperty(id, __GO_DATA_MODEL_Z_COORDINATES_SHIFT__, jni_double_vector, (void**) &zshift);
123 getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
125 if (polylineStyle == 1)
127 fillSegmentsDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
129 else if (polylineStyle == 2)
131 fillStairDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
133 else if (polylineStyle == 3)
135 fillVerticalLinesDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
137 else if (polylineStyle == 4)
139 fillSegmentsDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
141 else if (polylineStyle == 5)
143 fillSegmentsDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
145 else if (polylineStyle == 6)
147 fillVerticalBarsDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
149 else if (polylineStyle == 7)
151 fillHorizontalBarsDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
156 void PolylineDecomposer::fillSegmentsDecompositionVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation,
157 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
160 int componentIndices[3];
162 // TODO Optimize ? (test if s = 1 and t = 0, coordinateMask = 0 ...)
163 for (int i = 0; i < nPoints; i++)
165 /* Offset of a polyline vertex */
166 int v0 = elementsSize*i;
168 componentIndices[0] = i;
169 componentIndices[1] = i;
170 componentIndices[2] = i;
172 getAndWriteVertexToBuffer(buffer, v0, coordinates, componentIndices, nPoints, elementsSize,
173 xshift, yshift, zshift, coordinateMask, scale, translation, logMask);
178 void PolylineDecomposer::getAndWriteVertexToBuffer(float* buffer, int offset, double* coordinates, int* vertexIndices, int nPoints, int elementsSize,
179 double* xshift, double* yshift, double* zshift, int coordinateMask, double* scale, double* translation, int logMask)
181 double coordinate = 0.;
183 if (coordinateMask & 0x01)
185 coordinate = coordinates[vertexIndices[0]];
189 coordinate += xshift[vertexIndices[0]];
194 coordinate = DecompositionUtils::getLog10Value(coordinate);
197 buffer[offset +0] = (float)(coordinate * scale[0] + translation[0]);
200 if (coordinateMask & 0x02)
202 coordinate = coordinates[vertexIndices[1] + nPoints];
206 coordinate += yshift[vertexIndices[1]];
211 coordinate = DecompositionUtils::getLog10Value(coordinate);
214 buffer[offset +1] = (float)(coordinate * scale[1] + translation[1]);
217 if (coordinateMask & 0x04)
219 coordinate = coordinates[vertexIndices[2] + 2*nPoints];
223 coordinate += zshift[vertexIndices[2]];
228 coordinate = DecompositionUtils::getLog10Value(coordinate);
231 buffer[offset +2] = (float)(coordinate * scale[2] + translation[2]);
234 if((elementsSize == 4) && (coordinateMask & 0x08))
236 buffer[offset +3] = 1.0;
241 void PolylineDecomposer::fillStairDecompositionVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation,
242 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
245 int* piClosed = &closed;
247 /* Offsets of the left and right vertices (respectively) */
251 int componentIndices[3];
258 getGraphicObjectProperty(id, __GO_CLOSED__, jni_bool, (void**) &piClosed);
260 for (int i = 0; i < nPoints-1; i++)
262 v0 = elementsSize*2*i;
263 v1 = elementsSize*(2*i+1);
265 componentIndices[0] = i;
266 componentIndices[1] = i;
267 componentIndices[2] = i;
269 getAndWriteVertexToBuffer(buffer, v0, coordinates, componentIndices, nPoints, elementsSize, xshift, yshift, zshift, coordinateMask, scale, translation, logMask);
271 componentIndices[0] = i+1;
272 componentIndices[1] = i;
273 componentIndices[2] = i;
275 /* To be optimized: the y and z components are fetched and transformed twice */
276 getAndWriteVertexToBuffer(buffer, v1, coordinates, componentIndices, nPoints, elementsSize, xshift, yshift, zshift, coordinateMask, scale, translation, logMask);
280 v0 = elementsSize*2*(nPoints-1);
282 componentIndices[0] = nPoints-1;
283 componentIndices[1] = nPoints-1;
284 componentIndices[2] = nPoints-1;
286 getAndWriteVertexToBuffer(buffer, v0, coordinates, componentIndices, nPoints, elementsSize, xshift, yshift, zshift, coordinateMask, scale, translation, logMask);
289 * One additional vertex if closed
290 * Its x-coordinate is equal to the one of the polyline's first point
291 * whereas its y and z coordinates are equal to those of the last point.
295 v0 = elementsSize*(2*nPoints-1);
297 componentIndices[0] = 0;
298 componentIndices[1] = nPoints-1;
299 componentIndices[2] = nPoints-1;
301 getAndWriteVertexToBuffer(buffer, v0, coordinates, componentIndices, nPoints, elementsSize, xshift, yshift, zshift, coordinateMask, scale, translation, logMask);
306 void PolylineDecomposer::fillVerticalLinesDecompositionVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation,
307 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
309 for (int i = 0; i < nPoints; i++)
311 /* Offsets of the lower and upper vertices (respectively) */
315 /* Coordinates of the lower and upper vertices (respectively) */
319 v0 = elementsSize*2*i;
320 v1 = elementsSize*(2*i+1);
322 /* Lower and upper endpoints x coordinates */
323 if (coordinateMask & 0x01)
325 coord0 = coordinates[i];
326 coord1 = coordinates[i];
336 coord0 = DecompositionUtils::getLog10Value(coord0);
337 coord1 = DecompositionUtils::getLog10Value(coord1);
340 buffer[v0 +0] = (float)(coord0 * scale[0] + translation[0]);
341 buffer[v1 +0] = (float)(coord1 * scale[0] + translation[0]);
344 /* Lower and upper endpoints y coordinates */
345 if (coordinateMask & 0x02)
348 coord1 = coordinates[i + nPoints];
353 * Only the upper vertex's y coordinate is shifted,
354 * the lower vertex's one remains unchanged.
361 /* The lower endpoint's y coordinate is unchanged (it amounts to log10(1), which is 0) */
362 coord1 = DecompositionUtils::getLog10Value(coord1);
365 buffer[v0 +1] = (float)(coord0 * scale[1] + translation[1]);
366 buffer[v1 +1] = (float)(coord1 * scale[1] + translation[1]);
369 /* Lower and upper endpoints z coordinates */
370 if (coordinateMask & 0x04)
372 coord0 = coordinates[2*nPoints+i];
373 coord1 = coordinates[2*nPoints+i];
383 coord0 = DecompositionUtils::getLog10Value(coord0);
384 coord1 = DecompositionUtils::getLog10Value(coord1);
387 buffer[v0 +2] = (float)(coord0 * scale[2] + translation[2]);
388 buffer[v1 +2] = (float)(coord1 * scale[2] + translation[2]);
391 if((elementsSize == 4) && (coordinateMask & 0x08))
401 void PolylineDecomposer::writeBarVerticesToBuffer(float* buffer, int* offsets, int componentOffset, double* coordinates, double shift, int shiftUsed,
402 double scale, double translation, int logUsed)
406 coordinates[0] += shift;
407 coordinates[1] += shift;
408 coordinates[2] += shift;
409 coordinates[3] += shift;
411 coordinates[4] += shift;
416 coordinates[0] = DecompositionUtils::getLog10Value(coordinates[0]);
417 coordinates[1] = DecompositionUtils::getLog10Value(coordinates[1]);
418 coordinates[2] = DecompositionUtils::getLog10Value(coordinates[2]);
419 coordinates[3] = DecompositionUtils::getLog10Value(coordinates[3]);
421 coordinates[4] = DecompositionUtils::getLog10Value(coordinates[4]);
424 buffer[offsets[0] +componentOffset] = (float)(coordinates[0] * scale + translation);
425 buffer[offsets[1] +componentOffset] = (float)(coordinates[1] * scale + translation);
426 buffer[offsets[2] +componentOffset] = (float)(coordinates[2] * scale + translation);
427 buffer[offsets[3] +componentOffset] = (float)(coordinates[3] * scale + translation);
429 buffer[offsets[4] +componentOffset] = (float)(coordinates[4] * scale + translation);
432 void PolylineDecomposer::fillVerticalBarsDecompositionVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation,
433 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
435 double barWidth = 0.0;
436 double* pdBarWidth = &barWidth;
439 int *piShiftUsed = NULL;
442 * Offsets of the lower-left, lower-right, upper-right and upper-left bar vertices (respectively)
443 * and of the polyline vertex proper
448 * {x,y or z}-component values of a bar's 4 vertices (same ordering as the offsets)
449 * and of the polyline vertex proper.
456 getGraphicObjectProperty(id, __GO_BAR_WIDTH__, jni_double, (void**) &pdBarWidth);
458 piShiftUsed = &shiftUsed[0];
459 getGraphicObjectProperty(id, __GO_DATA_MODEL_X_COORDINATES_SHIFT_SET__, jni_double_vector, (void**) &piShiftUsed);
460 piShiftUsed = &shiftUsed[1];
461 getGraphicObjectProperty(id, __GO_DATA_MODEL_Y_COORDINATES_SHIFT_SET__, jni_double_vector, (void**) &piShiftUsed);
462 piShiftUsed = &shiftUsed[2];
463 getGraphicObjectProperty(id, __GO_DATA_MODEL_Z_COORDINATES_SHIFT_SET__, jni_double_vector, (void**) &piShiftUsed);
466 for (int i = 0; i < nPoints; i++)
468 offsets[0] = elementsSize*4*i;
469 offsets[1] = elementsSize*(4*i+1);
470 offsets[2] = elementsSize*(4*i+2);
471 offsets[3] = elementsSize*(4*i+3);
473 offsets[4] = elementsSize*(4*nPoints+i);
475 if (coordinateMask & 0x01)
477 coords[0] = coordinates[i] - 0.5*barWidth;
478 coords[1] = coordinates[i] + 0.5*barWidth;
479 coords[2] = coordinates[i] + 0.5*barWidth;
480 coords[3] = coordinates[i] - 0.5*barWidth;
482 coords[4] = coordinates[i];
489 writeBarVerticesToBuffer(buffer, offsets, 0, coords, shift, shiftUsed[0], scale[0], translation[0], logMask & 0x01);
492 if (coordinateMask & 0x02)
496 coords[2] = coordinates[i + nPoints];
497 coords[3] = coordinates[i + nPoints];
499 coords[4] = coordinates[i + nPoints];
509 * The two lower endpoints' y coordinates must be set to 1
510 * since writeBarVerticesToBuffer applies the logarithmic transformation.
516 writeBarVerticesToBuffer(buffer, offsets, 1, coords, shift, shiftUsed[1], scale[1], translation[1], logMask & 0x02);
519 if (coordinateMask & 0x04)
521 coords[0] = coordinates[i + 2 * nPoints];
522 coords[1] = coordinates[i + 2 * nPoints];
523 coords[2] = coordinates[i + 2 * nPoints];
524 coords[3] = coordinates[i + 2 * nPoints];
526 coords[4] = coordinates[i + 2* nPoints];
533 writeBarVerticesToBuffer(buffer, offsets, 2, coords, shift, shiftUsed[2], scale[2], translation[2], logMask & 0x04);
536 if((elementsSize == 4) && (coordinateMask & 0x08))
538 buffer[offsets[0] +3] = 1.0;
539 buffer[offsets[1] +3] = 1.0;
540 buffer[offsets[2] +3] = 1.0;
541 buffer[offsets[3] +3] = 1.0;
543 buffer[offsets[4] +3] = 1.0;
551 * To do: -refactor with fillVerticalBarsDecompositionVertices as these two functions are very similar, possibly by implementing
552 a PolylineBarDecomposer class.
554 void PolylineDecomposer::fillHorizontalBarsDecompositionVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation,
555 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
557 double barWidth = 0.0;
558 double* pdBarWidth = &barWidth;
561 int *piShiftUsed = NULL;
564 * Offsets of the lower-left, lower-right, upper-right and upper-left bar vertices (respectively)
565 * and of the polyline vertex proper
570 * {x,y or z}-component values of a bar's 4 vertices (same ordering as the offsets)
571 * and of the polyline vertex proper.
578 getGraphicObjectProperty(id, __GO_BAR_WIDTH__, jni_double, (void**) &pdBarWidth);
580 piShiftUsed = &shiftUsed[0];
581 getGraphicObjectProperty(id, __GO_DATA_MODEL_X_COORDINATES_SHIFT_SET__, jni_double_vector, (void**) &piShiftUsed);
582 piShiftUsed = &shiftUsed[1];
583 getGraphicObjectProperty(id, __GO_DATA_MODEL_Y_COORDINATES_SHIFT_SET__, jni_double_vector, (void**) &piShiftUsed);
584 piShiftUsed = &shiftUsed[2];
585 getGraphicObjectProperty(id, __GO_DATA_MODEL_Z_COORDINATES_SHIFT_SET__, jni_double_vector, (void**) &piShiftUsed);
587 for (int i = 0; i < nPoints; i++)
589 offsets[0] = elementsSize*4*i;
590 offsets[1] = elementsSize*(4*i+1);
591 offsets[2] = elementsSize*(4*i+2);
592 offsets[3] = elementsSize*(4*i+3);
594 offsets[4] = elementsSize*(4*nPoints+i);
596 /* The actual x coordinates correspond to the polyline's y coordinates. */
597 if (coordinateMask & 0x01)
601 coords[2] = coordinates[i + nPoints];
602 coords[3] = coordinates[i + nPoints];
604 coords[4] = coordinates[i];
611 writeBarVerticesToBuffer(buffer, offsets, 0, coords, shift, shiftUsed[1], scale[0], translation[0], logMask & 0x01);
614 /* The actual y coordinates correspond to the polyline's x coordinates. */
615 if (coordinateMask & 0x02)
617 coords[0] = coordinates[i] - 0.5*barWidth;
618 coords[1] = coordinates[i] + 0.5*barWidth;
619 coords[2] = coordinates[i] + 0.5*barWidth;
620 coords[3] = coordinates[i] - 0.5*barWidth;
622 coords[4] = coordinates[i + nPoints];
632 * The two lower endpoints' y coordinates must be set to 1
633 * since writeBarVerticesToBuffer applies the logarithmic transformation.
639 writeBarVerticesToBuffer(buffer, offsets, 1, coords, shift, shiftUsed[0], scale[1], translation[1], logMask & 0x02);
642 if (coordinateMask & 0x04)
644 coords[0] = coordinates[i + 2 * nPoints];
645 coords[1] = coordinates[i + 2 * nPoints];
646 coords[2] = coordinates[i + 2 * nPoints];
647 coords[3] = coordinates[i + 2 * nPoints];
649 coords[4] = coordinates[i + 2* nPoints];
656 writeBarVerticesToBuffer(buffer, offsets, 2, coords, shift, shiftUsed[2], scale[2], translation[2], logMask & 0x04);
659 if((elementsSize == 4) && (coordinateMask & 0x08))
661 buffer[offsets[0] +3] = 1.0;
662 buffer[offsets[1] +3] = 1.0;
663 buffer[offsets[2] +3] = 1.0;
664 buffer[offsets[3] +3] = 1.0;
666 buffer[offsets[4] +3] = 1.0;
675 * -implement for the other relevant polyline style values.
676 * -fix the no colors written problem (related to polyline C build functions, see below).
678 void PolylineDecomposer::fillColors(char* id, float* buffer, int bufferLength, int elementsSize)
681 char* parentFigure = NULL;
683 int interpColorMode = 0;
684 int* piInterpColorMode = &interpColorMode;
685 int polylineStyle = 0;
686 int* piPolylineStyle = &polylineStyle;
688 int *piNPoints = &nPoints;
689 int colormapSize = 0;
690 int* piColormapSize = &colormapSize;
691 int bufferOffset = 0;
692 int* interpColorVector = NULL;
694 double* colormap = NULL;
696 getGraphicObjectProperty(id, __GO_INTERP_COLOR_MODE__, jni_bool, (void**) &piInterpColorMode);
698 if (interpColorMode == 0)
703 getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
705 if (polylineStyle != 1)
710 getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
711 getGraphicObjectProperty(id, __GO_INTERP_COLOR_VECTOR__, jni_int_vector, (void**) &interpColorVector);
713 getGraphicObjectProperty(id, __GO_PARENT__, jni_string, (void**) &parent);
715 /* Temporary: to avoid getting a null parent_figure property when the object is built */
716 if (strcmp(parent, "") == 0)
721 getGraphicObjectProperty(id, __GO_PARENT_FIGURE__, jni_string, (void**) &parentFigure);
724 * In some cases, the polyline's parent figure may be unitialized, when this point is reached from the
725 * filled polygons build C functions (xfpolys, with several polygons and a color vector for each one).
726 * This check prevents from crashing when getting the colormap. However, it results in incorrectly
727 * black-filled polygons, as no colors are written.
728 * As the sequentially built polygons are inserted within a Compound object, the latter object may be
729 * still unattached to a Figure as its Polyline children are rendered. This occurs about once in 5 to 10,
730 * hence possibly caused by a race condition.
733 if (strcmp(parentFigure, "") == 0)
738 getGraphicObjectProperty(parentFigure, __GO_COLORMAP__, jni_double_vector, (void**) &colormap);
739 getGraphicObjectProperty(parentFigure, __GO_COLORMAP_SIZE__, jni_int, (void**) &piColormapSize);
742 * The interpolated color vector is a 3- or 4-element vector.
743 * However, if nPoints is greater than 4, we choose to output
744 * 4 colors (this behaviour is kept for compatibility, see fillTriangleIndices).
756 for (int i = 0; i < nPoints; i++)
758 ColorComputer::getDirectColor((double) interpColorVector[i] - 1.0, colormap, colormapSize, &buffer[bufferOffset]);
760 if (elementsSize == 4)
762 buffer[bufferOffset+3] = 1.0;
765 bufferOffset += elementsSize;
769 void PolylineDecomposer::fillTextureCoordinates(char* id, float* buffer, int bufferLength)
772 char* parentFigure = NULL;
774 int interpColorMode = 0;
775 int* piInterpColorMode = &interpColorMode;
776 int polylineStyle = 0;
777 int* piPolylineStyle = &polylineStyle;
779 int *piNPoints = &nPoints;
780 int colormapSize = 0;
781 int* piColormapSize = &colormapSize;
782 int bufferOffset = 0;
783 int* interpColorVector = NULL;
785 double* colormap = NULL;
787 getGraphicObjectProperty(id, __GO_INTERP_COLOR_MODE__, jni_bool, (void**) &piInterpColorMode);
789 if (interpColorMode == 0)
794 getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
796 if (polylineStyle != 1)
801 getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
802 getGraphicObjectProperty(id, __GO_INTERP_COLOR_VECTOR__, jni_int_vector, (void**) &interpColorVector);
804 getGraphicObjectProperty(id, __GO_PARENT__, jni_string, (void**) &parent);
806 /* Temporary: to avoid getting a null parent_figure property when the object is built */
807 if (strcmp(parent, "") == 0)
812 getGraphicObjectProperty(id, __GO_PARENT_FIGURE__, jni_string, (void**) &parentFigure);
815 * In some cases, the polyline's parent figure may be unitialized, when this point is reached from the
816 * filled polygons build C functions (xfpolys, with several polygons and a color vector for each one).
817 * This check prevents from crashing when getting the colormap. However, it results in incorrectly
818 * black-filled polygons, as no colors are written.
819 * As the sequentially built polygons are inserted within a Compound object, the latter object may be
820 * still unattached to a Figure as its Polyline children are rendered. This occurs about once in 5 to 10,
821 * hence possibly caused by a race condition.
824 if (strcmp(parentFigure, "") == 0)
829 getGraphicObjectProperty(parentFigure, __GO_COLORMAP__, jni_double_vector, (void**) &colormap);
830 getGraphicObjectProperty(parentFigure, __GO_COLORMAP_SIZE__, jni_int, (void**) &piColormapSize);
833 * The interpolated color vector is a 3- or 4-element vector.
834 * However, if nPoints is greater than 4, we choose to output
835 * 4 colors (this behaviour is kept for compatibility, see fillTriangleIndices).
847 for (int i = 0; i < nPoints; i++)
849 double index = (ColorComputer::getDirectIndex((double) interpColorVector[i] - 1.0, colormapSize) + 2.0 + COLOR_TEXTURE_OFFSET) / (double) (colormapSize + 2);
851 buffer[bufferOffset] = (float)index;
852 buffer[bufferOffset+1] = 0.0;
853 buffer[bufferOffset+2] = 0.0;
854 buffer[bufferOffset+3] = 1.0;
861 * To do: see fillIndices
862 * -take into account polyline_style.
864 int PolylineDecomposer::getIndicesSize(char* id)
867 int *piNPoints = &nPoints;
868 int polylineStyle = 0;
869 int* piPolylineStyle = &polylineStyle;
871 int* piClosed = &closed;
875 getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
876 getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
877 getGraphicObjectProperty(id, __GO_CLOSED__, jni_bool, (void**) &piClosed);
879 /* No facets if 0 points */
886 if (polylineStyle == 1)
893 /* Maximum number of triangles output by the triangulator */
894 nIndices = 3*(nPoints-2);
896 /* Arrowed segments */
897 else if (polylineStyle == 4)
899 nIndices = PolylineDecomposer::getArrowTriangleIndicesSize(nPoints, closed);
902 else if (polylineStyle == 5)
909 /* Maximum number of triangles output by the triangulator */
910 nIndices = 3*(nPoints-2);
912 /* Vertical bars plus segments */
913 else if (polylineStyle == 6)
915 nIndices = PolylineDecomposer::getBarsDecompositionTriangleIndicesSize(nPoints);
917 /* Horizontal bars plus segments */
918 else if (polylineStyle == 7)
920 nIndices = PolylineDecomposer::getBarsDecompositionTriangleIndicesSize(nPoints);
926 int PolylineDecomposer::getArrowTriangleIndicesSize(int nPoints, int closed)
936 nIndices = 3*(nPoints-1);
947 int PolylineDecomposer::getBarsDecompositionTriangleIndicesSize(int nPoints)
954 * -take into account the polyline style property (note: vertical bars -style 6- are filled
955 * whatever fill_mode's value), by implementing the relevant functions (see fillTriangleIndices),
956 * as the curve must be filled if fill_mode set to on, whatever its polyline style value.
958 int PolylineDecomposer::fillIndices(char* id, int* buffer, int bufferLength, int logMask)
960 double* coordinates = NULL;
961 double* xshift = NULL;
962 double* yshift = NULL;
963 double* zshift = NULL;
966 int* piNPoints = &nPoints;
967 int polylineStyle = 0;
968 int* piPolylineStyle = &polylineStyle;
970 int* piFillMode = &fillMode;
972 getGraphicObjectProperty(id, __GO_DATA_MODEL_COORDINATES__, jni_double_vector, (void**) &coordinates);
973 getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
974 getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
975 getGraphicObjectProperty(id, __GO_DATA_MODEL_X_COORDINATES_SHIFT__, jni_double_vector, (void**) &xshift);
976 getGraphicObjectProperty(id, __GO_DATA_MODEL_Y_COORDINATES_SHIFT__, jni_double_vector, (void**) &yshift);
977 getGraphicObjectProperty(id, __GO_DATA_MODEL_Z_COORDINATES_SHIFT__, jni_double_vector, (void**) &zshift);
979 getGraphicObjectProperty(id, __GO_FILL_MODE__, jni_bool, (void**) &piFillMode);
981 /* 0 triangles if 0 points */
987 if (polylineStyle == 1)
989 return fillTriangleIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, fillMode, polylineStyle);
991 else if (polylineStyle == 4)
993 return fillArrowTriangleIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift);
995 else if (polylineStyle == 5)
997 /* Set fill mode to on, since patches are always filled whatever fill mode's value */
998 return fillTriangleIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, 1, polylineStyle);
1000 else if (polylineStyle == 6)
1002 return fillBarsDecompositionTriangleIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift);
1004 else if (polylineStyle == 7)
1006 return fillBarsDecompositionTriangleIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift);
1012 int PolylineDecomposer::fillTriangleIndices(char* id, int* buffer, int bufferLength,
1013 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift, int fillMode, int polylineStyle)
1015 double coords[4][3];
1017 int interpColorMode = 0;
1018 int* piInterpColorMode = &interpColorMode;
1019 int triangulate = 0;
1025 /* At least 3 points needed */
1036 getGraphicObjectProperty(id, __GO_INTERP_COLOR_MODE__, jni_bool, (void**) &piInterpColorMode);
1039 * Do not triangulate if the interpolated color mode is set to 'on' and the polyline style is filled patch (5).
1040 * The quadrilateral facet decomposition function is used instead, if nPoints == 4,
1041 * for compatibility reasons, although triangulation could be used.
1043 if (interpColorMode && polylineStyle != 5)
1047 else if (nPoints > 3)
1049 /* Perform triangulation only if more than 3 points */
1055 Triangulator triangulator;
1061 for (int i = 0; i < nPoints; i++)
1063 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, i, &coords[0][0], &coords[0][1], &coords[0][2]);
1065 tmpValid = DecompositionUtils::isValid(coords[0][0], coords[0][1], coords[0][2]);
1069 tmpValid &= DecompositionUtils::isLogValid(coords[0][0], coords[0][1], coords[0][2], logMask);
1073 coords[0][0] = DecompositionUtils::getLog10Value(coords[0][0]);
1078 coords[0][1] = DecompositionUtils::getLog10Value(coords[0][1]);
1083 coords[0][2] = DecompositionUtils::getLog10Value(coords[0][2]);
1087 isValid &= tmpValid;
1094 triangulator.addPoint(coords[0][0], coords[0][1], coords[0][2]);
1103 triangulator.initialize();
1104 triangulator.triangulate();
1106 numTriangles = triangulator.getNumberTriangles();
1107 indices = triangulator.getIndices();
1109 for (int i = 0; i < numTriangles; i++)
1111 buffer[3*i] = indices[3*i];
1112 buffer[3*i+1] = indices[3*i+1];
1113 buffer[3*i+2] = indices[3*i+2];
1117 triangulator.clear();
1123 /* Do not triangulate: either the interpolation color mode is set to on or it is not and there are only 3 points. */
1125 /* 3 points: only one triangle output */
1128 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 0, &coords[0][0], &coords[0][1], &coords[0][2]);
1129 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 1, &coords[1][0], &coords[1][1], &coords[1][2]);
1130 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 2, &coords[2][0], &coords[2][1], &coords[2][2]);
1132 tmpValid = DecompositionUtils::isValid(coords[0][0], coords[0][1], coords[0][2]);
1133 tmpValid &= DecompositionUtils::isValid(coords[1][0], coords[1][1], coords[1][2]);
1134 tmpValid &= DecompositionUtils::isValid(coords[2][0], coords[2][1], coords[2][2]);
1140 tmpValid = DecompositionUtils::isLogValid(coords[0][0], coords[0][1], coords[0][2], logMask);
1141 tmpValid &= DecompositionUtils::isLogValid(coords[1][0], coords[1][1], coords[1][2], logMask);
1142 tmpValid &= DecompositionUtils::isLogValid(coords[2][0], coords[2][1], coords[2][2], logMask);
1143 isValid &= tmpValid;
1155 else if (nPoints >= 4)
1158 * 4 points: the quadrilateral facet decomposition algorithm is used.
1159 * If the Polyline has more than 4 points, we still output two triangles
1160 * corresponding to the first 4 points. This behaviour is kept for compatibility.
1161 * Possible correction: do not output indices if there are more than 4 points and
1162 * the interpolation color mode is set to on.
1164 int facetVertexIndices[4] = {0, 1, 2, 3};
1166 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 0, &coords[0][0], &coords[0][1], &coords[0][2]);
1167 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 1, &coords[1][0], &coords[1][1], &coords[1][2]);
1168 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 2, &coords[2][0], &coords[2][1], &coords[2][2]);
1169 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 3, &coords[3][0], &coords[3][1], &coords[3][2]);
1171 tmpValid = DecompositionUtils::isValid(coords[0][0], coords[0][1], coords[0][2]);
1172 tmpValid &= DecompositionUtils::isValid(coords[1][0], coords[1][1], coords[1][2]);
1173 tmpValid &= DecompositionUtils::isValid(coords[2][0], coords[2][1], coords[2][2]);
1174 tmpValid &= DecompositionUtils::isValid(coords[3][0], coords[3][1], coords[3][2]);
1180 tmpValid = DecompositionUtils::isLogValid(coords[0][0], coords[0][1], coords[0][2], logMask);
1181 tmpValid &= DecompositionUtils::isLogValid(coords[1][0], coords[1][1], coords[1][2], logMask);
1182 tmpValid &= DecompositionUtils::isLogValid(coords[2][0], coords[2][1], coords[2][2], logMask);
1183 tmpValid &= DecompositionUtils::isLogValid(coords[3][0], coords[3][1], coords[3][2], logMask);
1184 isValid &= tmpValid;
1189 DecompositionUtils::getDecomposedQuadTriangleIndices(coords, facetVertexIndices, buffer);
1199 int PolylineDecomposer::fillArrowTriangleIndices(char* id, int* buffer, int bufferLength,
1200 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
1205 int* piClosed = &closed;
1207 int currentValid = 0;
1210 int firstArrowVertex = 0;
1214 int numberValidIndices = 0;
1216 /* At least 2 points needed to form segments */
1222 getGraphicObjectProperty(id, __GO_CLOSED__, jni_bool, (void**) &piClosed);
1224 /* If closed, an additional segment is present */
1231 nArrows = nPoints-1;
1235 * Arrow head vertices are stored consecutively after all the line vertices.
1236 * Hence the offset to the first arrow vertex.
1238 firstArrowVertex = nPoints;
1240 for (int i = 0; i < nArrows; i++)
1242 /* Indices of the tip, left and right vertices */
1244 buffer[n] = firstArrowVertex + n;
1245 buffer[n + 1] = buffer[n] + 1;
1246 buffer[n + 2] = buffer[n] + 2;
1253 * Only bars are filled at the present moment, the curve is not.
1254 * See fillTriangleIndices for more information.
1256 int PolylineDecomposer::fillBarsDecompositionTriangleIndices(char* id, int* buffer, int bufferLength,
1257 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
1259 double barWidth = 0.0;
1260 double* pdBarWidth = &barWidth;
1263 int triangleIndices[6];
1265 int numberValidIndices = 0;
1272 getGraphicObjectProperty(id, __GO_BAR_WIDTH__, jni_double, (void**) &pdBarWidth);
1274 /* 0 indices if the bar width is invalid, as it is the same for all bars. */
1275 if (!DecompositionUtils::isValid(barWidth))
1281 * Gets the indices corresponding to a rectangle decomposed into 2 triangles.
1282 * All the bars are decomposed the same way.
1284 DecompositionUtils::getDecomposedRectangleTriangleIndices(triangleIndices);
1287 for (int i = 0; i < nPoints; i++)
1289 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, i, &coordsi[0], &coordsi[1], &coordsi[2]);
1291 if (DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]))
1293 if (logMask && !DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask))
1298 buffer[6*offset] = 4*i + triangleIndices[0];
1299 buffer[6*offset+1] = 4*i + triangleIndices[1];
1300 buffer[6*offset+2] = 4*i + triangleIndices[2];
1301 buffer[6*offset+3] = 4*i + triangleIndices[3];
1302 buffer[6*offset+4] = 4*i + triangleIndices[4];
1303 buffer[6*offset+5] = 4*i + triangleIndices[5];
1305 numberValidIndices += 6;
1311 return numberValidIndices;
1314 int PolylineDecomposer::getWireIndicesSize(char* id)
1317 int *piNPoints = &nPoints;
1318 int polylineStyle = 0;
1319 int* piPolylineStyle = &polylineStyle;
1322 int* piLineMode = &lineMode;
1325 int* piClosed = &closed;
1327 getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
1328 getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
1329 getGraphicObjectProperty(id, __GO_LINE_MODE__, jni_bool, (void**) &piLineMode);
1330 getGraphicObjectProperty(id, __GO_CLOSED__, jni_bool, (void**) &piClosed);
1332 /* No segments if 0 points */
1339 if (polylineStyle == 1)
1341 return getSegmentsDecompositionSegmentIndicesSize(nPoints, lineMode, closed);
1344 else if (polylineStyle == 2)
1346 return getStairDecompositionSegmentIndicesSize(nPoints, lineMode, closed);
1348 /* Vertical segments plus segments */
1349 else if (polylineStyle == 3)
1351 return getVerticalLinesDecompositionSegmentIndicesSize(nPoints, lineMode);
1353 /* Segments with arrow heads */
1354 else if (polylineStyle == 4)
1356 return getSegmentsDecompositionSegmentIndicesSize(nPoints, lineMode, closed);
1359 else if (polylineStyle == 5)
1361 return getSegmentsDecompositionSegmentIndicesSize(nPoints, lineMode, closed);
1363 /* Vertical bars plus segments */
1364 else if (polylineStyle == 6)
1366 return getBarsDecompositionSegmentIndicesSize(nPoints, lineMode);
1368 /* Horizontal bars plus segments */
1369 else if (polylineStyle == 7)
1371 return getBarsDecompositionSegmentIndicesSize(nPoints, lineMode);
1380 int PolylineDecomposer::getSegmentsDecompositionSegmentIndicesSize(int nPoints, int lineMode, int closed)
1404 int PolylineDecomposer::getStairDecompositionSegmentIndicesSize(int nPoints, int lineMode, int closed)
1415 return 2 * nPoints + 1;
1419 return 2 * nPoints - 1;
1428 int PolylineDecomposer::getVerticalLinesDecompositionSegmentIndicesSize(int nPoints, int lineMode)
1437 return 2*(nPoints) + 2*(nPoints-1);
1445 int PolylineDecomposer::getBarsDecompositionSegmentIndicesSize(int nPoints, int lineMode)
1454 return 2*4*(nPoints) + 2*(nPoints-1);
1458 return 2*4*(nPoints);
1462 int PolylineDecomposer::fillWireIndices(char* id, int* buffer, int bufferLength, int logMask)
1464 double* coordinates = NULL;
1465 double* xshift = NULL;
1466 double* yshift = NULL;
1467 double* zshift = NULL;
1469 int polylineStyle = 0;
1470 int* piPolylineStyle = &polylineStyle;
1472 int* piNPoints = &nPoints;
1474 int* piClosed = &closed;
1476 int* piLineMode = &lineMode;
1478 getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
1480 getGraphicObjectProperty(id, __GO_DATA_MODEL_COORDINATES__, jni_double_vector, (void**) &coordinates);
1481 getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
1482 getGraphicObjectProperty(id, __GO_DATA_MODEL_X_COORDINATES_SHIFT__, jni_double_vector, (void**) &xshift);
1483 getGraphicObjectProperty(id, __GO_DATA_MODEL_Y_COORDINATES_SHIFT__, jni_double_vector, (void**) &yshift);
1484 getGraphicObjectProperty(id, __GO_DATA_MODEL_Z_COORDINATES_SHIFT__, jni_double_vector, (void**) &zshift);
1486 getGraphicObjectProperty(id, __GO_LINE_MODE__, jni_bool, (void**) &piLineMode);
1487 getGraphicObjectProperty(id, __GO_CLOSED__, jni_bool, (void**) &piClosed);
1489 if (polylineStyle == 1)
1491 return fillSegmentsDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode, closed);
1493 else if (polylineStyle == 2)
1495 return fillStairDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode, closed);
1497 else if (polylineStyle == 3)
1499 return fillVerticalLinesDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode);
1501 else if (polylineStyle == 4)
1503 return fillSegmentsDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode, closed);
1505 else if (polylineStyle == 5)
1507 return fillSegmentsDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode, closed);
1509 else if (polylineStyle == 6)
1511 return fillBarsDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode);
1513 else if (polylineStyle == 7)
1515 return fillBarsDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode);
1521 int PolylineDecomposer::fillSegmentsDecompositionSegmentIndices(char* id, int* buffer, int bufferLength,
1522 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift, int lineMode, int closed)
1524 /* If less than 2 points, no segments */
1535 for (int i = 0; i < nPoints; i++)
1542 buffer[nPoints] = 0;
1545 return closed ? (nPoints + 1) : nPoints;
1548 int PolylineDecomposer::fillStairDecompositionSegmentIndices(char* id, int* buffer, int bufferLength,
1549 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift, int lineMode, int closed)
1552 double coordsip1[3];
1554 int currentValid = 0;
1555 int middleVertexValid = 0;
1559 int numberValidIndices = 0;
1561 /* If less than 2 points, no segments */
1572 for (int i = 0; i < 2 * nPoints - 1; i++)
1579 buffer[2 * nPoints - 1] = 2 * nPoints - 1;
1580 buffer[2 * nPoints] = 0;
1583 return closed ? (2 * nPoints + 1) : (2 * nPoints - 1);
1586 int PolylineDecomposer::fillVerticalLinesDecompositionSegmentIndices(char* id, int* buffer, int bufferLength,
1587 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift, int lineMode)
1592 int numberValidIndices = 0;
1599 /* Vertical lines */
1600 for (int i = 0; i < nPoints; i++)
1602 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, i, &coordsi[0], &coordsi[1], &coordsi[2]);
1604 if (DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]))
1606 if (logMask && !DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask))
1611 buffer[2*offset] = 2*i;
1612 buffer[2*offset+1] = 2*i+1;
1614 numberValidIndices += 2;
1625 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 0, &coordsi[0], &coordsi[1], &coordsi[2]);
1627 currentValid = DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]);
1631 currentValid &= DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask);
1634 for (int i = 0; i < nPoints-1; i++)
1636 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, i+1, &coordsi[0], &coordsi[1], &coordsi[2]);
1638 nextValid = DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]);
1642 nextValid &= DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask);
1645 if (currentValid && nextValid)
1647 buffer[2*offset] = 2*i+1;
1648 buffer[2*offset+1] = 2*(i+1)+1;
1650 numberValidIndices += 2;
1654 currentValid = nextValid;
1658 return numberValidIndices;
1662 int PolylineDecomposer::fillBarsDecompositionSegmentIndices(char* id, int* buffer, int bufferLength,
1663 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift, int lineMode)
1665 double barWidth = 0.0;
1666 double* pdBarWidth = &barWidth;
1669 int barWidthValid = 0;
1671 int numberValidIndices = 0;
1678 getGraphicObjectProperty(id, __GO_BAR_WIDTH__, jni_double, (void**) &pdBarWidth);
1680 barWidthValid = DecompositionUtils::isValid(barWidth);
1682 /* 0 bar segment indices if the bar width is invalid, as it is the same for all bars. */
1686 for (int i = 0; i < nPoints; i++)
1688 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, i, &coordsi[0], &coordsi[1], &coordsi[2]);
1690 if (DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]))
1692 if (logMask && !DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask))
1697 buffer[8*offset] = 4*i;
1698 buffer[8*offset+1] = 4*i+1;
1699 buffer[8*offset+2] = 4*i+1;
1700 buffer[8*offset+3] = 4*i+2;
1701 buffer[8*offset+4] = 4*i+2;
1702 buffer[8*offset+5] = 4*i+3;
1703 buffer[8*offset+6] = 4*i+3;
1704 buffer[8*offset+7] = 4*i;
1706 numberValidIndices += 8;
1722 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 0, &coordsi[0], &coordsi[1], &coordsi[2]);
1724 currentValid = DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]);
1728 currentValid &= DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask);
1731 for (int i = 0; i < nPoints-1; i++)
1733 getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, i+1, &coordsi[0], &coordsi[1], &coordsi[2]);
1735 nextValid = DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]);
1739 nextValid &= DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask);
1742 if (currentValid && nextValid)
1744 buffer[8*offset+2*loffset] = 4*nPoints +i;
1745 buffer[8*offset+2*loffset+1] = 4*nPoints +i+1;
1747 numberValidIndices += 2;
1751 currentValid = nextValid;
1755 return numberValidIndices;
1758 void PolylineDecomposer::getShiftedPolylinePoint(double* coordinates, double* xshift, double* yshift, double* zshift, int nPoints, int index,
1759 double* x, double* y, double* z)
1761 *x = coordinates[index];
1765 *x += xshift[index];
1768 *y = coordinates[index + nPoints];
1772 *y += yshift[index];
1775 *z = coordinates[index + 2*nPoints];
1779 *z += zshift[index];