예제 #1
0
        private void BuildImageWithUColor(
            IGraphicsContext3D g,
            IPlotArea gl,
            IReadOnlyList <double> lx,
            IReadOnlyList <double> ly,
            IROMatrix <double> matrix)
        {
            IPositionNormalUIndexedTriangleBuffer buffers;

            if (gl.ClipDataToFrame == LayerDataClipping.None && !_clipToLayer)
            {
                buffers = g.GetPositionNormalUIndexedTriangleBuffer(_material, null, _colorProvider);
            }
            else
            {
                var clipPlanes = new PlaneD3D[6];
                clipPlanes[0] = new PlaneD3D(1, 0, 0, 0);
                clipPlanes[1] = new PlaneD3D(-1, 0, 0, -gl.Size.X);
                clipPlanes[2] = new PlaneD3D(0, 1, 0, 0);
                clipPlanes[3] = new PlaneD3D(0, -1, 0, -gl.Size.Y);
                clipPlanes[4] = new PlaneD3D(0, 0, 1, 0);
                clipPlanes[5] = new PlaneD3D(0, 0, -1, -gl.Size.Z);

                buffers = g.GetPositionNormalUIndexedTriangleBuffer(_material, clipPlanes, _colorProvider);
            }

            var buf  = buffers;
            var offs = buf.VertexCount;

            int lxl   = lx.Count;
            int lyl   = ly.Count;
            int lxlm1 = lx.Count - 1;
            int lylm1 = ly.Count - 1;

            var vertexPoints = new PointD3D[lxl, lyl];
            var isValid      = new bool[lxl, lyl]; // array which stores for every point[i, j], if it is valid, to speed up calculations

            var zScale = gl.ZAxis;

            for (int i = 0; i < lx.Count; ++i)
            {
                for (int j = 0; j < ly.Count; ++j)
                {
                    double lz = zScale.PhysicalVariantToNormal(matrix[i, j]);
                    gl.CoordinateSystem.LogicalToLayerCoordinates(new Logical3D(lx[i], ly[j], lz), out var pt);

                    isValid[i, j]      = !pt.IsNaN;
                    vertexPoints[i, j] = pt;
                }
            }

            // ------------------------------------------------------------------
            // ------------------ Calculation of normals ------------------------
            // (this can be laborious, if both neighboring points are invalid)
            // ------------------------------------------------------------------
            for (int i = 0; i < lxl; ++i)
            {
                for (int j = 0; j < lyl; ++j)
                {
                    if (isValid[i, j])
                    {
                        var pm = vertexPoints[i, j];

                        // Strategy here: we calculate the vectors (right-left) and (upper-lower) and calculate the cross product. This is our normal vector.

                        // right - left
                        var vec1 = vertexPoints[(i < lxlm1 && isValid[i + 1, j]) ? i + 1 : i, j] -     // right side
                                   vertexPoints[(i > 0 && isValid[i - 1, j]) ? i - 1 : i, j];          // left side

                        if (vec1.IsEmpty)                                                              // if vector 1 is empty (because both the right _and_ the left neighbor points are invalid), then we have to try the diagonals
                        {
                            bool rightup = (i < lxlm1 && j < lylm1 && isValid[i + 1, j + 1]);          // right-up neighbor valid?
                            bool leftlow = (i > 0 && j > 0 && isValid[i - 1, j - 1]);                  // left-lower neighbor valid?
                            var  vec1a   = vertexPoints[rightup ? i + 1 : i, rightup ? j + 1 : j] -    // right / upper side
                                           vertexPoints[leftlow ? i - 1 : i, leftlow ? j - 1 : j];     // left / lower side

                            bool rightlow = (i < lxlm1 && j > 0 && isValid[i + 1, j - 1]);             // right-lower neighbor valid?
                            bool leftup   = (i > 0 && j < lylm1 && isValid[i - 1, j + 1]);             // left-upper neighbor valid?
                            var  vec1b    = vertexPoints[rightlow ? i + 1 : i, rightlow ? j - 1 : j] - // right / lower side
                                            vertexPoints[leftup ? i - 1 : i, leftup ? j + 1 : j];      // left / upper side

                            vec1 = vec1a + vec1b;                                                      // if one of these two vectors is empty, it doesn't matter for the addition
                        }

                        // upper - lower
                        var vec2 = vertexPoints[i, (j < lylm1 && isValid[i, j + 1]) ? j + 1 : j] -    // upper side
                                   vertexPoints[i, (j > 0 && isValid[i, j - 1]) ? j - 1 : j];         // lower side

                        if (vec2.IsEmpty)                                                             // if vector 2 is empty (because both the upper _and_ the lower neighbor points are invalid, then we have to try the diagonals
                        {
                            bool rightup = (i < lxlm1 && j < lylm1 && isValid[i + 1, j + 1]);         // right-up neighbor valid?
                            bool leftlow = (i > 0 && j > 0 && isValid[i - 1, j - 1]);                 // left-lower neighbor valid?
                            var  vec2a   = vertexPoints[rightup ? i + 1 : i, rightup ? j + 1 : j] -   // upper side / right
                                           vertexPoints[leftlow ? i - 1 : i, leftlow ? j - 1 : j];    // lower side / left

                            bool leftup   = (i > 0 && j < lylm1 && isValid[i - 1, j + 1]);            // left-upper neighbor valid?
                            bool rightlow = (i < lxlm1 && j > 0 && isValid[i + 1, j - 1]);            // right-lower neighbor valid?
                            var  vec2b    = vertexPoints[leftup ? i - 1 : i, leftup ? j + 1 : j] -    // upper side / left
                                            vertexPoints[rightlow ? i + 1 : i, rightlow ? j - 1 : j]; // lower side / right

                            vec2 = vec2a + vec2b;                                                     // if one of these two vectors is empty, it doesn't matter for the addition
                        }

                        var    normal = VectorD3D.CrossProduct(vec1, vec2).Normalized;
                        double lz     = null != _colorScale?_colorScale.PhysicalVariantToNormal(matrix[i, j]) : zScale.PhysicalVariantToNormal(matrix[i, j]);

                        buf.AddTriangleVertex(pm.X, pm.Y, pm.Z, normal.X, normal.Y, normal.Z, lz);
                        buf.AddTriangleVertex(pm.X, pm.Y, pm.Z, -normal.X, -normal.Y, -normal.Z, lz);
                    }
                    else // if this point is not valid, we still add triangle vertices to keep the order of points
                    {
                        buf.AddTriangleVertex(double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN);
                        buf.AddTriangleVertex(double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN);
                    }
                }
            }

            // now add the triangle indices
            // we don't make the effort to sort out the invalid point, because they are suppressed anyways
            for (int i = 0; i < lxlm1; ++i)
            {
                for (int j = 0; j < lylm1; ++j)
                {
                    // upper side
                    buf.AddTriangleIndices(offs + 0, offs + 2 * lyl, offs + 2);
                    buf.AddTriangleIndices(offs + 2, offs + 2 * lyl, offs + 2 * lyl + 2);

                    // from below
                    buf.AddTriangleIndices(offs + 0 + 1, offs + 2 + 1, offs + 2 * lyl + 1);
                    buf.AddTriangleIndices(offs + 2 + 1, offs + 2 * lyl + 2 + 1, offs + 2 * lyl + 1);

                    offs += 2;
                }
                offs += 2; // one extra increment because inner loop ends at one less than array size
            }
        }
예제 #2
0
		private void BuildImageWithUColor(
				IGraphicsContext3D g,
				IPlotArea gl,
				IROVector lx,
				IROVector ly,
				IROMatrix matrix)
		{
			IPositionNormalUIndexedTriangleBuffer buffers;

			if (gl.ClipDataToFrame == LayerDataClipping.None && !_clipToLayer)
			{
				buffers = g.GetPositionNormalUIndexedTriangleBuffer(_material, null, _colorProvider);
			}
			else
			{
				var clipPlanes = new PlaneD3D[6];
				clipPlanes[0] = new PlaneD3D(1, 0, 0, 0);
				clipPlanes[1] = new PlaneD3D(-1, 0, 0, -gl.Size.X);
				clipPlanes[2] = new PlaneD3D(0, 1, 0, 0);
				clipPlanes[3] = new PlaneD3D(0, -1, 0, -gl.Size.Y);
				clipPlanes[4] = new PlaneD3D(0, 0, 1, 0);
				clipPlanes[5] = new PlaneD3D(0, 0, -1, -gl.Size.Z);

				buffers = g.GetPositionNormalUIndexedTriangleBuffer(_material, clipPlanes, _colorProvider);
			}

			var buf = buffers;
			var offs = buf.VertexCount;

			int lxl = lx.Length;
			int lyl = ly.Length;
			int lxlm1 = lx.Length - 1;
			int lylm1 = ly.Length - 1;

			var vertexPoints = new PointD3D[lxl, lyl];
			var vertexColors = new Color[lxl, lyl];

			PointD3D pt;
			var zScale = gl.ZAxis;
			for (int i = 0; i < lx.Length; ++i)
			{
				for (int j = 0; j < ly.Length; ++j)
				{
					double lz = zScale.PhysicalVariantToNormal(matrix[i, j]);
					gl.CoordinateSystem.LogicalToLayerCoordinates(new Logical3D(lx[i], ly[j], lz), out pt);

					vertexPoints[i, j] = pt;
					vertexColors[i, j] = _colorProvider.GetColor(null == _colorScale ? lz : _colorScale.PhysicalVariantToNormal(matrix[i, j])); // either use the scale of the coordinate system or our own color scale
				}
			}

			// calculate the normals
			for (int i = 0; i < lx.Length; ++i)
			{
				for (int j = 0; j < ly.Length; ++j)
				{
					var pm = vertexPoints[i, j];
					var vec1 = vertexPoints[Math.Min(i + 1, lxlm1), j] - vertexPoints[Math.Max(i - 1, 0), j];
					var vec2 = vertexPoints[i, Math.Min(j + 1, lylm1)] - vertexPoints[i, Math.Max(j - 1, 0)];

					var normal = VectorD3D.CrossProduct(vec1, vec2).Normalized;
					double lz = null != _colorScale ? _colorScale.PhysicalVariantToNormal(matrix[i, j]) : zScale.PhysicalVariantToNormal(matrix[i, j]);
					buf.AddTriangleVertex(pm.X, pm.Y, pm.Z, normal.X, normal.Y, normal.Z, lz);
					buf.AddTriangleVertex(pm.X, pm.Y, pm.Z, -normal.X, -normal.Y, -normal.Z, lz);
				}
			}

			for (int i = 0; i < lxlm1; ++i)
			{
				for (int j = 0; j < lylm1; ++j)
				{
					// upper side
					buf.AddTriangleIndices(offs + 0, offs + 2 * lyl, offs + 2);
					buf.AddTriangleIndices(offs + 2, offs + 2 * lyl, offs + 2 * lyl + 2);

					// from below
					buf.AddTriangleIndices(offs + 0 + 1, offs + 2 + 1, offs + 2 * lyl + 1);
					buf.AddTriangleIndices(offs + 2 + 1, offs + 2 * lyl + 2 + 1, offs + 2 * lyl + 1);

					offs += 2;
				}
				offs += 2; // one extra increment because inner loop ends at one less than array size
			}
		}