private void ButtonImport_OnClick(object sender, RoutedEventArgs e) { List <int> SelectedGroups = new List <int>(); for (int i = 0; i < AvailableGroups.Count; i++) { foreach (var selectedItem in ListGroups.SelectedItems) { if ((string)selectedItem == AvailableGroups[i]) { SelectedGroups.Add(i); } } } using (Stream SessionStream = File.OpenRead(SessionPath)) { XPathDocument Doc = new XPathDocument(SessionStream); XPathNavigator Reader = Doc.CreateNavigator(); Reader.MoveToRoot(); int iGroup = 0; foreach (XPathNavigator groupNav in Reader.Select("//PointGroups/Group")) { if (SelectedGroups.Contains(iGroup)) { PointGroup NewGroup = new PointGroup { Name = XMLHelper.LoadAttribute(groupNav, "Name", "Group " + (MainWindow.Options.Membrane.PointGroups.Count + 1)), Size = XMLHelper.LoadAttribute(groupNav, "Size", 10), Color = ColorHelper.LoadAttribute(groupNav, "Color", ColorHelper.SpectrumColor(MainWindow.Options.Membrane.PointGroups.Count, 0.3f)) }; NewGroup.PointCloud.GLContext = MainWindow.Options.Viewport.GetControl(); foreach (XPathNavigator pointNav in groupNav.SelectChildren("Point", "")) { int TriangleID = XMLHelper.LoadAttribute(pointNav, "ID", 0); SurfacePoint NewPoint = new SurfacePoint(OpenGLHelper.LoadAttribute(pointNav, "Position", new Vector3(0)), MainWindow.Options.Membrane.SurfaceMesh.Triangles[TriangleID < MainWindow.Options.Membrane.SurfaceMesh.Triangles.Count ? TriangleID : 0], OpenGLHelper.LoadAttribute(pointNav, "Barycentric", new Vector3(0)), XMLHelper.LoadAttribute(pointNav, "Offset", 0f), OpenGLHelper.LoadAttribute(pointNav, "Orientation", new Vector3(0)).X); NewGroup.Points.Add(NewPoint); } MainWindow.Options.Membrane.PointGroups.Add(NewGroup); NewGroup.IsVisible = XMLHelper.LoadAttribute(groupNav, "IsVisible", true); } iGroup++; } } if (SelectedGroups.Count > 0) { MainWindow.Options.Viewport.Redraw(); } Close(); }
/// <summary> /// Инициализация матрицы /// </summary> /// <param name="surfacePoint">Ключевая(начальная) точка массива</param> /// <param name="countpointX">Количество точек/рядов сканирования по оси X</param> /// <param name="countpointY">Количество точек/строк сканирования по оси Y</param> /// <param name="stepx">Интервал между точками</param> /// <param name="stepy">Интервал между точками</param> public static void Init(SurfacePoint surfacePoint, int countpointX, int countpointY, float stepx, float stepy) { _primaryPosition = surfacePoint == null ? new SurfacePoint() : new SurfacePoint(surfacePoint); _countPointX = countpointX; _countPointY = countpointY; _stepX = stepx; _stepY = stepy; SpeedMove = 200; SpeedScan = 50; Matrix = new SurfacePoint[_countPointX, _countPointY]; // заполним пустыми данными for (int y = 0; y < _countPointY; y++) { for (int x = 0; x < _countPointX; x++) { SurfacePoint tmPoint = new SurfacePoint(); if (surfacePoint != null) { tmPoint.PosX = (x * stepx) + surfacePoint.PosX; tmPoint.PosY = (y * stepy) + surfacePoint.PosY; tmPoint.PosZ = surfacePoint.PosZ; } tmPoint.PosZ = 0; Matrix[x, y] = new SurfacePoint(tmPoint); } } NotInit = false; }
public override (int, int, float) SelectBidirPath(SurfacePoint cameraPoint, Vector3 outDir, int pixelIndex, RNG rng) { // Select a single vertex from the entire cache at random var(path, vertex) = vertexSelector.Select(rng); return(path, vertex, BidirSelectDensity()); }
/// <summary> /// Клонирование данных из существующей точки /// </summary> /// <param name="_point"></param> public SurfacePoint(SurfacePoint _point) { PosX = _point.PosX; PosY = _point.PosY; PosZ = _point.PosZ; //deltaZ = _point.deltaZ; }
/// <summary> /// Computes the inverse jacobian for the mapping from surface area around "to" to the sphere around "from". /// /// Required for integrals that perform this change of variables (e.g., next event estimation). /// /// Multiplying solid angle pdfs by this value computes the corresponding surface area density. /// Dividing surface area pdfs by this value computes the corresponding solid angle density. /// /// This function simply computes the cosine formed by the normal at "to" and the direction from "to" to "from". /// The absolute value of that cosine is then divided by the squared distance between the two points: /// /// result = cos(normal_to, from - to) / ||from - to||^2 /// </summary> /// <param name="from">The position at which the hemispherical distribution is defined.</param> /// <param name="to">The point on the surface area that is projected onto the hemisphere.</param> /// <returns>Inverse jacobian, multiply solid angle densities by this value.</returns> public static float SurfaceAreaToSolidAngle(SurfacePoint from, SurfacePoint to) { var dir = to.Position - from.Position; var distSqr = dir.LengthSquared(); return(MathF.Abs(Vector3.Dot(to.Normal, -dir)) / (distSqr * MathF.Sqrt(distSqr))); }
protected virtual void ApplyGravity() { if (customGravity) { _relativeGravity = customGravityDirection.normalized * rigidbody.mass * gravityScale * -Physics2D.gravity.y; } else { if (alignToSurface) { surface = GetSurfacePoint(maxSurfaceDistance); if (surface) { // rotate object to have the same normal as the surface point transform.rotation = Quaternion.LookRotation(Vector3.forward, surface.normal); // Set relative gravity to oposite the normal _relativeGravity = -surface.normal * rigidbody.mass * gravityScale * -Physics2D.gravity.y; } } else if (flipWithPlayer) { _relativeGravity = GameMaster.gameMaster.relativeGravityDirection * rigidbody.mass * gravityScale * -Physics2D.gravity.y; } } if (invertGravity) { _relativeGravity *= -1; } if (Application.isPlaying && useGravity) { rigidbody.AddForce(_relativeGravity); } }
public void EmittedRays_Pdf_ShouldBeOneSided() { var mesh = new Mesh( new Vector3[] { new Vector3(-1, 10, -1), new Vector3(1, 10, -1), new Vector3(1, 10, 1), new Vector3(-1, 10, 1) }, new int[] { 0, 1, 2, 0, 2, 3 }, shadingNormals: new Vector3[] { new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0) } ); var emitter = new DiffuseEmitter(mesh, RgbColor.White); var dummyHit = new SurfacePoint { Mesh = mesh }; var p1 = emitter.PdfRay(dummyHit, new Vector3(0, 1, 1)); var p2 = emitter.PdfRay(dummyHit, new Vector3(0, -1, 1)); Assert.True(p1 > 0); Assert.Equal(0, p2); }
public void Emission_ShouldBeOneSided() { var mesh = new Mesh( new Vector3[] { new Vector3(-1, 10, -1), new Vector3(1, 10, -1), new Vector3(1, 10, 1), new Vector3(-1, 10, 1) }, new int[] { 0, 1, 2, 0, 2, 3 }, shadingNormals: new Vector3[] { new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0) } ); var emitter = new DiffuseEmitter(mesh, RgbColor.White); var dummyHit = new SurfacePoint { Mesh = mesh }; var r1 = emitter.EmittedRadiance(dummyHit, new Vector3(0, 1, 1)); var r2 = emitter.EmittedRadiance(dummyHit, new Vector3(0, -1, 1)); Assert.True(r1.R > 0); Assert.Equal(0, r2.R); }
public override RgbColor OnCameraHit(CameraPath path, RNG rng, int pixelIndex, Ray ray, SurfacePoint hit, float pdfFromAncestor, RgbColor throughput, int depth, float toAncestorJacobian) { RgbColor value = RgbColor.Black; // Was a light hit? Emitter light = scene.QueryEmitter(hit); if (light != null) { value += throughput * OnEmitterHit(light, hit, ray, path, toAncestorJacobian); } // Perform connections if the maximum depth has not yet been reached if (depth < MaxDepth) { if (EnableConnections) { value += throughput * BidirConnections(pixelIndex, hit, -ray.Direction, rng, path, toAncestorJacobian); } var nextEvtSum = RgbColor.Black; var nextEvtSumSqr = RgbColor.Black; for (int i = 0; i < NumShadowRays; ++i) { var c = throughput * PerformNextEventEstimation(ray, hit, rng, path, toAncestorJacobian); nextEvtSum += c; nextEvtSumSqr += c * c; value += c; } } return(value); }
public virtual RgbColor EstimatePixelValue(SurfacePoint cameraPoint, Vector2 filmPosition, Ray primaryRay, float pdfFromCamera, RgbColor initialWeight, RNG rng) { // Trace the primary ray into the scene var hit = scene.Raytracer.Trace(primaryRay); if (!hit) { return(scene.Background?.EmittedRadiance(primaryRay.Direction) ?? RgbColor.Black); } // Gather nearby photons float radius = scene.Radius / 100.0f; RgbColor estimate = photonMap.Accumulate(radius, hit, -primaryRay.Direction, Merge, radius); // Add contribution from directly visible light sources var light = scene.QueryEmitter(hit); if (light != null) { estimate += light.EmittedRadiance(hit, -primaryRay.Direction); } return(estimate); }
public EarthPoint InverseProject(Point Point, int Zoom) { double mpp = _scales[Zoom]; var surfacePoint = new SurfacePoint(Point.X * mpp, -Point.Y * mpp); return((EarthPoint)surfacePoint); }
public void MarsLanderNewData(int positionX, int positionY, int hSpeed, int vSpeed, int rotate, int power) { this.currentPoint = new SurfacePoint(positionX, positionY); this._hSpeed = hSpeed; this._vSpeed = vSpeed; this._rotate = rotate; this._power = power; }
/// <summary> /// The shading value at a primary hit point. The default implementation uses "eye light shading", /// i.e., the cosine between the outgoing direction and the normal. /// </summary> public virtual RgbColor ComputeColor(SurfacePoint hit, Vector3 from) { float cosine = Math.Abs(Vector3.Dot(hit.Normal, from)); cosine /= hit.Normal.Length(); cosine /= from.Length(); return(RgbColor.White * cosine); }
//нахождение высоты Z точки p0, лежащей на прямой между точками p3 p4 (прямая паралельна оси Y) private static SurfacePoint CalcPY(SurfacePoint p1, SurfacePoint p2, SurfacePoint p0) { SurfacePoint ReturnPoint = new SurfacePoint(p0.PosX, p0.PosY, p0.PosZ); ReturnPoint.PosZ = p1.PosZ + (((p1.PosZ - p2.PosZ) / (p1.PosY - p2.PosY)) * (p0.PosY - p1.PosY)); return(ReturnPoint); }
public double ClosestDistanceTo(SurfacePoint ladderPoint) { double powOfX = Math.Pow((this._x - ladderPoint._x), 2); double powOfY = Math.Pow((this._y - ladderPoint._y), 2); double distance = Math.Sqrt(powOfX + powOfY); return(distance); }
public override RgbColor EmittedRadiance(SurfacePoint point, Vector3 direction) { if (Vector3.Dot(point.ShadingNormal, direction) < 0) { return(RgbColor.Black); } return(Radiance); }
SurfacePoint Lin1(SurfacePoint p1, SurfacePoint p2, double t) { SurfacePoint q = new SurfacePoint(); q.Vertex.X = p2.Vertex.X * t + p1.Vertex.X * (1 - t); q.Vertex.Y = p2.Vertex.Y * t + p1.Vertex.Y * (1 - t); q.Vertex.Z = p2.Vertex.Z * t + p1.Vertex.Z * (1 - t); return(q); }
public static bool IsVisible( Vector3d bodyCentredVesselPosition, SurfacePoint surfacePoint) { Vector3d surfaceToSatellite = bodyCentredVesselPosition - surfacePoint.bodyCentredSurfacePosition; return(Vector3d.Dot(surfaceToSatellite, surfacePoint.vertical) > 0); }
/* * Корректировка высоты по оси Z, у точки №5, зная высоту по Z у точек 1,2,3,4 * * /\ ось Y * | * | (точка №1) -------------*--------------- (точка №2) * | | * | | * | | * | (точка №5) * | | * | | * | (точка №3) -------------*--------------- (точка №4) * | * | * *----------------------------------------------------------------> ось X * Корректировка выполняется следующим образом: * 1) зная координату X у точки 5, и координаты точек 1 и 2, вычисляем высоту Z в точке которая находится на линии точек 1,2 и перпендикулярно 5-й точке (получает точку №12) * 2) Тоже самое вычисляется для точки на линии точек 3,4 (получает точку №34) * 3) Зная координаты точек №12, №34 и значение по оси Y у точки 5, вычисляем высоту по оси Z */ /// <summary> /// Функция корректирует высоту по оси Z /// </summary> /// <param name="p1">первая точка первой линии X</param> /// <param name="p2">вторая точка первой линии X</param> /// <param name="p3">первая точка второй линии X</param> /// <param name="p4">вторая точка второй линии X</param> /// <param name="p5">точка у которой нужно скорректировать высоту</param> /// <returns></returns> private static SurfacePoint GetZ(SurfacePoint p1, SurfacePoint p2, SurfacePoint p3, SurfacePoint p4, SurfacePoint p5) { SurfacePoint p12 = CalcPX(p1, p2, p5); SurfacePoint p34 = CalcPX(p3, p4, p5); SurfacePoint p1234 = CalcPY(p12, p34, p5); return(p1234); }
public override RgbColor EmittedRadiance(SurfacePoint point, Vector3 direction) { float cosine = Vector3.Dot(point.ShadingNormal, direction) / direction.Length(); if (cosine < 0) { return(RgbColor.Black); } return(radiance * MathF.Pow(cosine, exponent) * normalizationFactor); }
//нахождение высоты Z точки p0, лежащей на прямой которая паралельна оси X private static SurfacePoint CalcPX(SurfacePoint p1, SurfacePoint p2, SurfacePoint p0) { SurfacePoint ReturnPoint = new SurfacePoint(p0.PosX, p0.PosY, p0.PosZ); ReturnPoint.PosZ = p1.PosZ + (((p1.PosZ - p2.PosZ) / (p1.PosX - p2.PosX)) * (p0.PosX - p1.PosX)); //TODO: учесть на будущее что точка 1 и 2 могут лежать не на одной паралльной линии оси Х ReturnPoint.PosY = p1.PosY; return(ReturnPoint); }
void UpdateTangents() { for (int i = 0; i < surfacePoints.Length; i++) { SurfacePoint surfacePointLeft = surfacePoints[(i - 1 + surfacePoints.Length) % surfacePoints.Length]; SurfacePoint surfacePointRight = surfacePoints[(i + 1) % surfacePoints.Length]; SurfacePoint targetPoint = surfacePoints[i]; Vector3 tangent = surfacePointLeft.transform.position - surfacePointRight.transform.position; spriteShapeManager.UpdateTangentAt(i, tangent); } }
bool GetIsOnSolidGround(SurfacePoint surfacePoint) { if (surfacePoint.otherCollider.attachedRigidbody == null) { return(true); } if (surfacePoint.otherCollider.attachedRigidbody.isKinematic) { return(true); } return(false); }
public SurfaceSatelliteGeometry( Vector3d bodyCentredVesselPosition, SurfacePoint surfacePoint) { Vector3d surfaceToSatellite = bodyCentredVesselPosition - surfacePoint.bodyCentredSurfacePosition; range = surfaceToSatellite.magnitude; cosZenithalAngle = Vector3d.Dot(surfaceToSatellite, surfacePoint.vertical) / range; absSinSwathAngle = 0; }
public static SunSurfaceGeometry FromSunDirection( SurfacePoint surfacePoint, Vector3d bodyCentredSunDirection) { double cosSolarZenithAngle = Vector3d.Dot(surfacePoint.vertical, bodyCentredSunDirection); return(new SunSurfaceGeometry { cosSolarZenithAngle = cosSolarZenithAngle, reflectedRay = -bodyCentredSunDirection + 2 * cosSolarZenithAngle * surfacePoint.vertical }); }
static void Main(string[] args) { string[] inputs; int surfaceN = int.Parse(Console.ReadLine()); // the number of points used to draw the surface of Mars. SurfacePoint[] allPoints = new SurfacePoint[surfaceN]; for (int i = 0; i < surfaceN; i++) { inputs = Console.ReadLine().Split(' '); int landX = int.Parse(inputs[0]); // X coordinate of a surface point. (0 to 6999) int landY = int.Parse(inputs[1]); // Y coordinate of a surface point. By linking all the points together in a sequential fashion, you form the surface of Mars. allPoints[i] = new SurfacePoint(landX, landY); } List <SurfacePoint> allPairsOfStraightPoints = new List <SurfacePoint>(); for (int cur = 0; cur < (allPoints.Length - 1); cur++) { if (allPoints[cur].CheckThisSurface(allPoints[cur + 1])) { allPairsOfStraightPoints.Add(allPoints[cur]); allPairsOfStraightPoints.Add(allPoints[cur + 1]); } } MarsLander mLander = new MarsLander(); bool closestLandingSurfaceChecked = false; // game loop while (true) { inputs = Console.ReadLine().Split(' '); int X = int.Parse(inputs[0]); int Y = int.Parse(inputs[1]); int hSpeed = int.Parse(inputs[2]); // the horizontal speed (in m/s), can be negative. int vSpeed = int.Parse(inputs[3]); // the vertical speed (in m/s), can be negative. int fuel = int.Parse(inputs[4]); // the quantity of remaining fuel in liters. int rotate = int.Parse(inputs[5]); // the rotation angle in degrees (-90 to 90). int power = int.Parse(inputs[6]); // the thrust power (0 to 4). mLander.MarsLanderNewData(X, Y, hSpeed, vSpeed, rotate, power); // Write an action using Console.WriteLine() // To debug: Console.Error.WriteLine("Debug messages..."); if (!closestLandingSurfaceChecked) { mLander.CheckClosestSurfaceForLander(allPairsOfStraightPoints); closestLandingSurfaceChecked = true; } Console.WriteLine(mLander.LanderNextMove()); } }
// Frank-Wolfe convex optimization algorithm. Returns closest point to a simplex in a signed distance function. private static void FrankWolfe <T>(ref T function, int simplexStart, int simplexSize, NativeArray <float4> positions, NativeArray <float4> radii, NativeArray <int> simplices, ref float4 convexPoint, ref float convexThickness, ref float4 convexBary, ref SurfacePoint pointInFunction, int maxIterations, float tolerance) where T : struct, IDistanceFunction { for (int i = 0; i < maxIterations; ++i) { // sample target function: function.Evaluate(convexPoint, ref pointInFunction); // find descent direction: int descent = 0; float gap = float.MinValue; for (int j = 0; j < simplexSize; ++j) { int particle = simplices[simplexStart + j]; float4 candidate = positions[particle] - convexPoint; // here, we adjust the candidate by projecting it to the engrosed simplex's surface: candidate -= pointInFunction.normal * (radii[particle].x - convexThickness); float corr = math.dot(-pointInFunction.normal, candidate); if (corr > gap) { descent = j; gap = corr; } } // if the duality gap is below tolerance threshold, stop iterating. if (gap < tolerance) { break; } // update the barycentric coords using 2/(i+2) as the step factor float step = 0.3f * 2.0f / (i + 2); convexBary *= 1 - step; convexBary[descent] += step; // get cartesian coordinates of current solution: GetCartesianConvexAttrib(simplexStart, simplexSize, simplices, positions, radii, convexBary, out convexPoint, out convexThickness); } }
private void InitPoint(ref SurfacePoint point, double x, double y, double?z) { point.X = x; point.Y = y; point.Z = z; if (z != null) { point.XLeftProj = GetXProj(x, z.Value, true); point.XRightProj = GetXProj(x, z.Value, false); point.YProj = GetYProj(y, z.Value); } }
void DetermineWallPoints(List <ContactPoint> contactPoints, SurfacePoint surfacePoint, out List <ContactPoint> wallPoints) { wallPoints = new List <ContactPoint>(); for (int i = 0; i < contactPoints.Count; i++) { ContactPoint point = contactPoints[i]; float pointAngle = Vector3.Angle(point.normal, rb.transform.up); if (pointAngle > moveSlopeAngleLimit) { wallPoints.Add(point); } } }
protected override RgbColor OnHit(Ray ray, SurfacePoint hit, float pdfFromAncestor, RgbColor throughput, int depth, float toAncestorJacobian) { // Add the next vertex lastId = cache.AddVertex(new PathVertex { Point = hit, PdfFromAncestor = pdfFromAncestor, PdfReverseAncestor = nextReversePdf, Weight = throughput, AncestorId = lastId, Depth = (byte)depth }, pathIdx); return(RgbColor.Black); }
Vector SampleEmitters(Vector rayDirection, SurfacePoint surfacePoint, Sampler random) { Vector radiance; // single emitter sample, ideal diffuse BRDF: // reflected = (emitivity * solidangle) * (emitterscount) * // (cos(emitdirection) / pi * reflectivity) // -- SurfacePoint does the first and last parts (in separate methods) // get position on an emitter Vector emitterPosition; Triangle emitter; scene.GetEmitter(random, out emitterPosition, out emitter); // check an emitter was found if (null != emitter) { // make direction to emit point Vector emitDirection = (emitterPosition - surfacePoint.Position).Unitize(); // send shadow ray Triangle hitObject; Vector hitPosition; scene.GetIntersection(surfacePoint.Position, emitDirection, surfacePoint.Item, out hitObject, out hitPosition); StatsCounter.RayTraced(); // if unshadowed, get inward emission value Vector emissionIn = null; if ((null == hitObject) || (emitter == hitObject)) emissionIn = new SurfacePoint(emitter, emitterPosition).GetEmission(surfacePoint.Position, -emitDirection, true); else emissionIn = new Vector(); // get amount reflected by surface radiance = surfacePoint.GetReflection(emitDirection, emissionIn * scene.GetEmittersCount(), -rayDirection); } else radiance = new Vector(); return radiance; }
public Vector GetRadiance(Vector rayOrigin, Vector rayDirection, Sampler random, Triangle lastHit) { // intersect ray with scene Triangle pHitObject; Vector hitPosition; scene.GetIntersection(rayOrigin, rayDirection, lastHit, out pHitObject, out hitPosition); Vector radiance; if (null != pHitObject) { // make surface point of intersection SurfacePoint surfacePoint = new SurfacePoint(pHitObject, hitPosition); // local emission only for first-hit if (lastHit != null) radiance = Vector.ZERO; else radiance = surfacePoint.GetEmission(rayOrigin, -rayDirection, false); // add emitter sample radiance = radiance + SampleEmitters(rayDirection, surfacePoint, random); // add recursive reflection // // single hemisphere sample, ideal diffuse BRDF: // reflected = (inradiance * pi) * (cos(in) / pi * color) * reflectance // -- reflectance magnitude is 'scaled' by the russian roulette, cos is // importance sampled (both done by SurfacePoint), and the pi and 1/pi // cancel out Vector nextDirection; Vector color; // check surface bounces ray, recurse if (surfacePoint.GetNextDirection(random, -rayDirection, out nextDirection, out color)) radiance = radiance + (color * GetRadiance(surfacePoint.Position, nextDirection, random, surfacePoint.Item)); } else // no hit: default/background scene emission radiance = scene.GetDefaultEmission(-rayDirection); return radiance; }
private void InitPoint(ref SurfacePoint point, double x, double y, double? z) { point.X = x; point.Y = y; point.Z = z; if (z != null) { point.XLeftProj = GetXProj(x, z.Value, true); point.XRightProj = GetXProj(x, z.Value, false); point.YProj = GetYProj(y, z.Value); } }
private void ButtonImport_OnClick(object sender, RoutedEventArgs e) { List<int> SelectedGroups = new List<int>(); for (int i = 0; i < AvailableGroups.Count; i++) { foreach (var selectedItem in ListGroups.SelectedItems) if ((string)selectedItem == AvailableGroups[i]) SelectedGroups.Add(i); } using (Stream SessionStream = File.OpenRead(SessionPath)) { XPathDocument Doc = new XPathDocument(SessionStream); XPathNavigator Reader = Doc.CreateNavigator(); Reader.MoveToRoot(); int iGroup = 0; foreach (XPathNavigator groupNav in Reader.Select("//PointGroups/Group")) { if (SelectedGroups.Contains(iGroup)) { PointGroup NewGroup = new PointGroup { Name = XMLHelper.LoadAttribute(groupNav, "Name", "Group " + (MainWindow.Options.Membrane.PointGroups.Count + 1)), Size = XMLHelper.LoadAttribute(groupNav, "Size", 10), Color = ColorHelper.LoadAttribute(groupNav, "Color", ColorHelper.SpectrumColor(MainWindow.Options.Membrane.PointGroups.Count, 0.3f)) }; NewGroup.PointCloud.GLContext = MainWindow.Options.Viewport.GetControl(); foreach (XPathNavigator pointNav in groupNav.SelectChildren("Point", "")) { int TriangleID = XMLHelper.LoadAttribute(pointNav, "ID", 0); SurfacePoint NewPoint = new SurfacePoint(OpenGLHelper.LoadAttribute(pointNav, "Position", new Vector3(0)), MainWindow.Options.Membrane.SurfaceMesh.Triangles[TriangleID < MainWindow.Options.Membrane.SurfaceMesh.Triangles.Count ? TriangleID : 0], OpenGLHelper.LoadAttribute(pointNav, "Barycentric", new Vector3(0)), XMLHelper.LoadAttribute(pointNav, "Offset", 0f), OpenGLHelper.LoadAttribute(pointNav, "Orientation", new Vector3(0)).X); NewGroup.Points.Add(NewPoint); } MainWindow.Options.Membrane.PointGroups.Add(NewGroup); NewGroup.IsVisible = XMLHelper.LoadAttribute(groupNav, "IsVisible", true); } iGroup++; } } if (SelectedGroups.Count > 0) MainWindow.Options.Viewport.Redraw(); Close(); }
/// <summary> /// Вычисление высоты Z по переданным 2-м координатам /// </summary> public static float GetPosZ(float _x, float _y) { //точка которую нужно отобразить SurfacePoint pResult = new SurfacePoint(_x, _y, 0); //поиск ближайшей точки из матрицы int indexXmin = 0; int indexYmin = 0; for (int x = 0; x < Matrix.GetLength(0) - 1; x++) { for (int y = 0; y < Matrix.GetLength(1) - 1; y++) { if (_x > Matrix[x, 0].PosX && _x < Matrix[x + 1, 0].PosX && Matrix[0, y].PosY < _y && Matrix[0, y + 1].PosY > _y) { indexXmin = x; indexYmin = y; } } } SurfacePoint p1 = new SurfacePoint(Matrix[indexXmin, indexYmin].PosX, Matrix[indexXmin, indexYmin].PosY, Matrix[indexXmin, indexYmin].PosZ); SurfacePoint p3 = new SurfacePoint(Matrix[indexXmin, indexYmin + 1].PosX, Matrix[indexXmin, indexYmin + 1].PosY, Matrix[indexXmin, indexYmin + 1].PosZ); SurfacePoint p2 = new SurfacePoint(Matrix[indexXmin + 1, indexYmin].PosX, Matrix[indexXmin + 1, indexYmin].PosY, Matrix[indexXmin + 1, indexYmin].PosZ); SurfacePoint p4 = new SurfacePoint(Matrix[indexXmin + 1, indexYmin + 1].PosX, Matrix[indexXmin + 1, indexYmin + 1].PosY, Matrix[indexXmin + 1, indexYmin + 1].PosZ); SurfacePoint p12 = CalcPX(p1, p2, pResult); SurfacePoint p34 = CalcPX(p3, p4, pResult); SurfacePoint p1234 = CalcPY(p12, p34, pResult); return p1234.PosZ; //return 0; }
//нахождение высоты Z точки p0, лежащей на прямой между точками p3 p4 (прямая паралельна оси Y) private static SurfacePoint CalcPY(SurfacePoint p1, SurfacePoint p2, SurfacePoint p0) { SurfacePoint ReturnPoint = new SurfacePoint(p0.PosX, p0.PosY, p0.PosZ); ReturnPoint.PosZ = p1.PosZ + (((p1.PosZ - p2.PosZ) / (p1.PosY - p2.PosY)) * (p0.PosY - p1.PosY)); return ReturnPoint; }
//нахождение высоты Z точки p0, лежащей на прямой которая паралельна оси X private static SurfacePoint CalcPX(SurfacePoint p1, SurfacePoint p2, SurfacePoint p0) { SurfacePoint ReturnPoint = new SurfacePoint(p0.PosX, p0.PosY, p0.PosZ); ReturnPoint.PosZ = p1.PosZ + (((p1.PosZ - p2.PosZ) / (p1.PosX - p2.PosX)) * (p0.PosX - p1.PosX)); //TODO: учесть на будущее что точка 1 и 2 могут лежать не на одной паралльной линии оси Х ReturnPoint.PosY = p1.PosY; return ReturnPoint; }
/* * Корректировка высоты по оси Z, у точки №5, зная высоту по Z у точек 1,2,3,4 * * /\ ось Y * | * | (точка №1) -------------*--------------- (точка №2) * | | * | | * | | * | (точка №5) * | | * | | * | (точка №3) -------------*--------------- (точка №4) * | * | * *----------------------------------------------------------------> ось X * Корректировка выполняется следующим образом: * 1) зная координату X у точки 5, и координаты точек 1 и 2, вычисляем высоту Z в точке которая находится на линии точек 1,2 и перпендикулярно 5-й точке (получает точку №12) * 2) Тоже самое вычисляется для точки на линии точек 3,4 (получает точку №34) * 3) Зная координаты точек №12, №34 и значение по оси Y у точки 5, вычисляем высоту по оси Z */ /// <summary> /// Функция корректирует высоту по оси Z /// </summary> /// <param name="p1">первая точка первой линии X</param> /// <param name="p2">вторая точка первой линии X</param> /// <param name="p3">первая точка второй линии X</param> /// <param name="p4">вторая точка второй линии X</param> /// <param name="p5">точка у которой нужно скорректировать высоту</param> /// <returns></returns> private static SurfacePoint GetZ(SurfacePoint p1, SurfacePoint p2, SurfacePoint p3, SurfacePoint p4, SurfacePoint p5) { SurfacePoint p12 = CalcPX(p1, p2, p5); SurfacePoint p34 = CalcPX(p3, p4, p5); SurfacePoint p1234 = CalcPY(p12, p34, p5); return p1234; }