private void DoChildSwapping(int node)
        {
            var children    = sg.Children[node];
            var hasImpreved = true;

            while (hasImpreved)
            {
                hasImpreved = false;
                var energy = ChildEnergy(node);
                foreach (var childPair in children.AllPairs())
                {
                    var child1 = childPair.First;
                    var child2 = childPair.Second;

                    if (radii[child1] != radii[child2] ||
                        nodeExternalConnections.ContainsKey(child1) ||
                        nodeExternalConnections.ContainsKey(child2))
                    {
                        continue;
                    }

                    CodingHelper.Swap(ref positions[child1], ref positions[child2]);
                    var newEnergy = ChildEnergy(node);
                    if (newEnergy < energy)
                    {
                        energy      = newEnergy;
                        hasImpreved = true;
                    }
                    else
                    {
                        CodingHelper.Swap(ref positions[child1], ref positions[child2]);
                    }
                }
            }
        }
Example #2
0
 public bool TrySortSubscriptionsByDependencies(IServiceEventDependencyGraph dependencyGraph, out string contradictionString)
 {
     while (true)
     {
         var foundWrongOrder = false;
         for (var i = 0; i < Subscriptions.Count - 1; i++)
         {
             for (var j = i + 1; j < Subscriptions.Count; j++)
             {
                 var comparisonResult = CompareSubscriptions(Subscriptions[i], Subscriptions[j], dependencyGraph, out contradictionString);
                 if (comparisonResult == SubscriptionDependencyComparisonResult.Contradicting)
                 {
                     return(false);
                 }
                 if (comparisonResult != SubscriptionDependencyComparisonResult.FirstDependsOnSecond)
                 {
                     continue;
                 }
                 CodingHelper.Swap(subscriptions, i, j);
                 foundWrongOrder = true;
             }
         }
         if (!foundWrongOrder)
         {
             break;
         }
     }
     contradictionString = null;
     return(true);
 }
 private static LineSegment3 To3(Vector2 p1, Vector2 p2, Transform transform, bool swap)
 {
     if (swap)
     {
         CodingHelper.Swap(ref p1, ref p2);
     }
     return(new LineSegment3(To3(p1) * transform, To3(p2) * transform));
 }
        public override IResource GetNew(IResourceSource resourceSource)
        {
            var cSource             = (Source)resourceSource;
            var verticalIndexOffset = 2 * cSource.HalfNumCircleSegments;
            var vertices            = new VertexPosTanNormTex[verticalIndexOffset * cSource.HalfNumCircleSegments];

            for (int i = 0; i < cSource.HalfNumCircleSegments; i++)
            {
                for (int j = 0; j < verticalIndexOffset; j++)
                {
                    var u   = (float)j / (verticalIndexOffset - 1);
                    var v   = (float)i / (cSource.HalfNumCircleSegments - 1);
                    var phi = MathHelper.TwoPi * u + MathHelper.Pi;
                    var psi = MathHelper.PiOver2 - MathHelper.Pi * v;
                    var z   = MathHelper.Cos(phi) * MathHelper.Cos(psi);
                    var x   = MathHelper.Sin(phi) * MathHelper.Cos(psi);
                    var y   = MathHelper.Sin(psi);

                    var normal   = new Vector3(x, y, z);
                    var position = normal;
                    var tangent  = Vector3.Cross(Vector3.UnitY, normal).Normalize();
                    var texcoord = new Vector2(u, v);
                    vertices[i * verticalIndexOffset + j] = new VertexPosTanNormTex(
                        position, tangent, normal, texcoord);
                }
            }
            var indexList = new List <int>();

            for (int i = 0; i < cSource.HalfNumCircleSegments - 1; i++)
            {
                for (int j = 0; j < verticalIndexOffset - 1; j++)
                {
                    var topLeftIndex = i * verticalIndexOffset + j;
                    indexList.Add(topLeftIndex);
                    indexList.Add(topLeftIndex + 1);
                    indexList.Add(topLeftIndex + 1 + verticalIndexOffset);
                    indexList.Add(topLeftIndex);
                    indexList.Add(topLeftIndex + 1 + verticalIndexOffset);
                    indexList.Add(topLeftIndex + verticalIndexOffset);
                }
            }
            var indices = indexList.ToArray();

            if (cSource.Inverse)
            {
                for (int i = 0; i < vertices.Length; i++)
                {
                    vertices[i].Normal = -vertices[i].Normal;
                }
                for (int i = 0; i < indices.Length; i += 3)
                {
                    CodingHelper.Swap(ref indices[i + 1], ref indices[i + 2]);
                }
            }
            return(ExplicitModel.FromVertices(vertices, indices, ExplicitModelPrimitiveTopology.TriangleList).WithSource(cSource));
        }
Example #5
0
 private void SwapPlaces(ChildPlace place1, ChildPlace place2)
 {
     if (place1.Child.HasValue)
     {
         positions[place1.Child.Value] = place2.Position;
     }
     if (place2.Child.HasValue)
     {
         positions[place2.Child.Value] = place1.Position;
     }
     CodingHelper.Swap(ref place1.Child, ref place2.Child);
 }
Example #6
0
        public static void Intersect(Circle2 c1, Circle2 c2, out Circle2?circle2Result, out Vector2?pointRes1, out Vector2?pointRes2)
        {
            circle2Result = null;
            pointRes1     = null;
            pointRes2     = null;
            if (c1.Center == c2.Center)
            {
                if (c1.Radius == c2.Radius)
                {
                    circle2Result = c1;
                }
                return;
            }
            if (c1.Radius < c2.Radius)
            {
                CodingHelper.Swap(ref c1, ref c2);
            }
            var firstToSecond = c2.Center - c1.Center;
            var distance      = firstToSecond.Length();
            var dir           = firstToSecond / distance;
            var radiusSum     = c1.Radius + c2.Radius;

            if (radiusSum < distance)
            {
                return;
            }
            if (radiusSum == distance)
            {
                pointRes1 = c1.Center + dir * c1.Radius;
                return;
            }
            if (distance + c2.Radius > c1.Radius)
            {
                var offset = (distance.Sq() + c1.Radius.Sq() - c2.Radius.Sq()) / (2 * distance);
                var center = c1.Center + dir * offset;
                var radius = MathHelper.Sqrt(c1.Radius.Sq() - offset.Sq());
                var ortho  = new Vector2(dir.Y, -dir.X).Normalize();
                pointRes1 = center + ortho * radius;
                pointRes2 = center - ortho * radius;
                return;
            }
            if (distance + c2.Radius == c1.Radius)
            {
                pointRes1 = c1.Center + dir * c1.Radius;
                return;
            }
        }
Example #7
0
        public static void Intersect(Sphere s1, Sphere s2, out Sphere?sphereResult, out Circle3?circleResult, out Vector3?pointResult)
        {
            sphereResult = null;
            circleResult = null;
            pointResult  = null;
            if (s1.Center == s2.Center)
            {
                if (s1.Radius == s2.Radius)
                {
                    sphereResult = s1;
                }
                return;
            }
            if (s1.Radius < s2.Radius)
            {
                CodingHelper.Swap(ref s1, ref s2);
            }
            var firstToSecond = s2.Center - s1.Center;
            var distance      = firstToSecond.Length();
            var dir           = firstToSecond / distance;
            var radiusSum     = s1.Radius + s2.Radius;

            if (radiusSum < distance)
            {
                return;
            }
            if (radiusSum == distance)
            {
                pointResult = s1.Center + dir * s1.Radius;
                return;
            }
            if (distance + s2.Radius > s1.Radius)
            {
                var offset = (distance.Sq() + s1.Radius.Sq() - s2.Radius.Sq()) / (2 * distance);
                var center = s1.Center + dir * offset;
                var radius = MathHelper.Sqrt(s1.Radius * s1.Radius - offset * offset);
                circleResult = new Circle3(center, dir, radius);
                return;
            }
            if (distance + s2.Radius == s1.Radius)
            {
                pointResult = s1.Center + dir * s1.Radius;
                return;
            }
        }
        private static void GetExternalPart(LineSegment3 segment, BuildingPrimitive primitive, List <LineSegment3> results)
        {
            var invTransform   = primitive.Transform.Invert();
            var transformedSeg = new LineSegment3(segment.Point1 * invTransform, segment.Point2 * invTransform);
            var seg            = new LineSegment2(transformedSeg.Point1.Xz, transformedSeg.Point2.Xz);

            if (primitive.Type == BuildingPrimitiveType.Rectangle)
            {
                var rect     = new AaRectangle2(Vector2.Zero, primitive.Scale.X, primitive.Scale.Z);
                var conains1 = rect.ContainsPoint(seg.Point1);
                var conains2 = rect.ContainsPoint(seg.Point2);
                if (conains1 && conains2)
                {
                    return;
                }
                if (!conains1 && !conains2)
                {
                    var p = Vector2.Zero;
                    int c = 0;
                    foreach (var rectSegment in rect.GetSegments())
                    {
                        var rsi = rectSegment.Intersect(seg);
                        if (rsi.HasValue)
                        {
                            p += rsi.Value;
                            c++;
                        }
                    }

                    if (c > 0)
                    {
                        var t = ((p / c) - seg.Point1).Length() / (seg.Point2 - seg.Point1).Length();
                        var m = segment.Point1 + (segment.Point2 - segment.Point1) * t;
                        GetExternalPart(new LineSegment3(segment.Point1, m), primitive, results);
                        GetExternalPart(new LineSegment3(m, segment.Point2), primitive, results);
                        return;
                    }

                    results.Add(segment);
                    return;
                }

                var swap = conains1;
                if (swap)
                {
                    CodingHelper.Swap(ref seg.Point1, ref seg.Point2);
                }
                var inter = seg.Intersect(new LineSegment2(
                                              new Vector2(-primitive.Scale.X, -primitive.Scale.Z),
                                              new Vector2(-primitive.Scale.X, primitive.Scale.Z)));
                if (inter.HasValue)
                {
                    var rs1 = To3(seg.Point1, inter.Value, primitive.Transform, swap);
                    results.Add(rs1);
                    return;
                }
                inter = seg.Intersect(new LineSegment2(
                                          new Vector2(primitive.Scale.X, -primitive.Scale.Z),
                                          new Vector2(primitive.Scale.X, primitive.Scale.Z)));
                if (inter.HasValue)
                {
                    var rs1 = To3(seg.Point1, inter.Value, primitive.Transform, swap);
                    results.Add(rs1);
                    return;
                }
                inter = seg.Intersect(new LineSegment2(
                                          new Vector2(-primitive.Scale.X, primitive.Scale.Z),
                                          new Vector2(primitive.Scale.X, primitive.Scale.Z)));
                if (inter.HasValue)
                {
                    var rs1 = To3(seg.Point1, inter.Value, primitive.Transform, swap);
                    results.Add(rs1);
                    return;
                }
                inter = seg.Intersect(new LineSegment2(
                                          new Vector2(-primitive.Scale.X, -primitive.Scale.Z),
                                          new Vector2(primitive.Scale.X, -primitive.Scale.Z)));
                if (inter.HasValue)
                {
                    var rs1 = To3(seg.Point1, inter.Value, primitive.Transform, swap);
                    results.Add(rs1);
                    return;
                }

                var rs2 = segment;
                results.Add(rs2);
                return;
            }
            else
            {
                var circle = new Circle2(Vector2.Zero, primitive.Scale.X);

                var conains1 = circle.Contains(seg.Point1);
                var conains2 = circle.Contains(seg.Point2);
                if (conains1 && conains2)
                {
                    return;
                }
                if (!conains1 && !conains2)
                {
                    var rs1 = segment;
                    results.Add(rs1);
                    return;
                }

                var swap = conains1;
                if (swap)
                {
                    CodingHelper.Swap(ref seg.Point1, ref seg.Point2);
                }

                var dpp   = seg.Point2 - seg.Point1;
                var dpc   = seg.Point1;
                var a     = dpp.LengthSquared();
                var b     = Vector2.Dot(dpp, dpc);
                var c     = dpc.LengthSquared() - circle.Radius.Sq();
                var discr = b * b - a * c;
                if (discr < 0)
                {
                    results.Add(segment);
                    return;
                }
                if (discr < MathHelper.Eps5)
                {
                    results.Add(segment);
                    return;
                    //var l = -b / a;
                    //if (0 <= l && l <= 1)
                }
                {
                    var sqrdscr = MathHelper.Sqrt(discr);
                    var l1      = (-b + sqrdscr) / a;
                    var l2      = (-b - sqrdscr) / a;
                    if (0 <= l1 && l1 <= 1)
                    {
                        var rs1 = To3(seg.Point1, Vector2.Lerp(seg.Point1, seg.Point2, l1), primitive.Transform, swap);
                        results.Add(rs1);
                    }

                    if (0 <= l2 && l2 <= 1)
                    {
                        var rs1 = To3(seg.Point1, Vector2.Lerp(seg.Point1, seg.Point2, l2), primitive.Transform, swap);
                        results.Add(rs1);
                    }
                }
            }
        }
        private static List <BuildingWallSegment> BuildWallBasementManaged(List <BuildingPrimitive> primitives)
        {
            var wallSegments      = new List <BuildingWallSegment>();
            var primitiveSegments = new List <LineSegment3>();
            var filteredSegments1 = new List <LineSegment3>();
            var filteredSegments2 = new List <LineSegment3>();

            for (int i = 0; i < primitives.Count; i++)
            {
                var primitive = primitives[i];
                primitiveSegments.Clear();
                if (primitive.IsMainCorridor)
                {
                    var p1 = new Vector3(-primitive.Scale.X, 0, primitive.Scale.Z) * primitive.Transform;
                    var p2 = new Vector3(-primitive.Scale.X, 0, -primitive.Scale.Z) * primitive.Transform;
                    var p3 = new Vector3(primitive.Scale.X, 0, -primitive.Scale.Z) * primitive.Transform;
                    var p4 = new Vector3(primitive.Scale.X, 0, primitive.Scale.Z) * primitive.Transform;
                    primitiveSegments.Add(new LineSegment3(p2, p3));
                    primitiveSegments.Add(new LineSegment3(p4, p1));
                }
                else if (primitive.Type == BuildingPrimitiveType.Rectangle)
                {
                    var p1 = new Vector3(-primitive.Scale.X, 0, primitive.Scale.Z) * primitive.Transform;
                    var p2 = new Vector3(-primitive.Scale.X, 0, -primitive.Scale.Z) * primitive.Transform;
                    var p3 = new Vector3(primitive.Scale.X, 0, -primitive.Scale.Z) * primitive.Transform;
                    var p4 = new Vector3(primitive.Scale.X, 0, primitive.Scale.Z) * primitive.Transform;
                    primitiveSegments.Add(new LineSegment3(p1, p2));
                    primitiveSegments.Add(new LineSegment3(p2, p3));
                    primitiveSegments.Add(new LineSegment3(p3, p4));
                    primitiveSegments.Add(new LineSegment3(p4, p1));
                }
                else
                {
                    var scale     = primitive.Scale.X;
                    var currPoint = scale * Vector3.UnitX * primitive.Transform;
                    for (int j = 1; j < 33; j++)
                    {
                        var prevPoint = currPoint;
                        var angle     = MathHelper.TwoPi * j / (33 - 1);
                        currPoint = (scale * new Vector3(MathHelper.Cos(angle), 0, MathHelper.Sin(angle))) * primitive.Transform;
                        primitiveSegments.Add(new LineSegment3(prevPoint, currPoint));
                    }
                }

                foreach (var segment in primitiveSegments)
                {
                    filteredSegments1.Clear();
                    filteredSegments2.Clear();
                    filteredSegments1.Add(segment);
                    for (int j = 0; j < primitives.Count; j++)
                    {
                        if (j == i)
                        {
                            continue;
                        }
                        var checkingPrimitive = primitives[j];
                        foreach (var subseg in filteredSegments1)
                        {
                            GetExternalPart(subseg, checkingPrimitive, filteredSegments2);
                        }
                        filteredSegments1.Clear();
                        CodingHelper.Swap(ref filteredSegments1, ref filteredSegments2);
                    }
                    wallSegments.AddRange(filteredSegments1.Select(x => new BuildingWallSegment {
                        Basement = x, Height = BuildingConstants.CeilingHeight
                    }));
                }
            }

            return(wallSegments);
        }
Example #10
0
        private static AssetLoadResultByLoader Load(AssetLoadInfo loadInfo, void *dicomManager)
        {
            int width, height, depth;

            CheckSuccess(DicomProject.AnalyzerGetDimensions(dicomManager, 1, &width, &height, &depth));

            var lowerBuffer  = new byte[width * height];
            var higherBuffer = new byte[width * height];
            var vertexList   = new List <VertexPosNormTex>();

            fixed(byte *pBuffer = higherBuffer)
            {
                int bufferSize = higherBuffer.Length;
                int bytesWritten;

                CheckSuccess(DicomProject.AnalyzerGetMonochromePixelDataBufferOfSlice(dicomManager, 1, pBuffer, &bufferSize, &bytesWritten));
            }

            for (int z = 1; z < depth; z++)
            {
                CodingHelper.Swap(ref lowerBuffer, ref higherBuffer);

                fixed(byte *pBuffer = higherBuffer)
                {
                    int bufferSize = higherBuffer.Length;
                    int bytesWritten;

                    CheckSuccess(DicomProject.AnalyzerGetMonochromePixelDataBufferOfSlice(dicomManager, z + 1, pBuffer, &bufferSize, &bytesWritten));
                }

                for (int y = 0; y < height - 1; y++)
                {
                    for (int x = 0; x < width - 1; x++)
                    {
                        var vx = (100f / width) * x - 50f;
                        var vy = (100f / height) * y - 50f;
                        var vz = (100f / depth) * z - 50f;

                        var yStride = width;

                        var mcCube = new MCCubeCornerScalarStruct
                        {
                            CubeDim   = new IrtPtType(100.0 / width, 100.0 / height, 100.0 / depth),
                            Vrtx0Lctn = new IrtPtType(vx, vy, vz)
                        };
                        mcCube.Corners[0] = UNormToDouble(lowerBuffer[yStride * y + x]);
                        mcCube.Corners[1] = UNormToDouble(lowerBuffer[yStride * y + (x + 1)]);
                        mcCube.Corners[2] = UNormToDouble(lowerBuffer[yStride * (y + 1) + (x + 1)]);
                        mcCube.Corners[3] = UNormToDouble(lowerBuffer[yStride * (y + 1) + x]);
                        mcCube.Corners[4] = UNormToDouble(higherBuffer[yStride * y + x]);
                        mcCube.Corners[5] = UNormToDouble(higherBuffer[yStride * y + (x + 1)]);
                        mcCube.Corners[6] = UNormToDouble(higherBuffer[yStride * (y + 1) + (x + 1)]);
                        mcCube.Corners[7] = UNormToDouble(higherBuffer[yStride * (y + 1) + x]);
                        // todo: use ref instead
                        EstimateGradient(&mcCube);
                        var MCPolys = Irit.MCThresholdCube(&mcCube, 0.5);

                        while (MCPolys != null)
                        {
                            var texCoord = new Vector2((float)x / width, (float)z / depth);

                            var vertex0    = MCPolys->GetClarityVertex(0, texCoord);
                            var vertexCurr = MCPolys->GetClarityVertex(1, texCoord);

                            for (var i = 2; i < MCPolys->NumOfVertices; i++)
                            {
                                var vertexPrev = vertexCurr;

                                vertexCurr = MCPolys->GetClarityVertex(i, texCoord);
                                vertexList.Add(vertex0);
                                vertexList.Add(vertexPrev);
                                vertexList.Add(vertexCurr);
                            }

                            //Irit.IritFree(MCPolys);

                            MCPolys = MCPolys->Pnext;
                        }
                    }
                }
            }

            var pack = new ResourcePack(ResourceVolatility.Immutable);

            var rawVerticesData = new RawDataResource(ResourceVolatility.Immutable, vertexList.Count * sizeof(VertexPosNormTex));

            pack.AddSubresource("VertexData", rawVerticesData);
            var pRawData = (VertexPosNormTex *)rawVerticesData.Map();

            for (int i = 0; i < vertexList.Count; i++)
            {
                pRawData[i] = vertexList[i];
            }
            rawVerticesData.Unmap(true);

            var vertexSet = new FlexibleModelVertexSet(ResourceVolatility.Immutable, new[] { new RawDataResSubrange(rawVerticesData, 0) }, VertexPosNormTex.GetElementsInfos(0), null);

            pack.AddSubresource("ModelVertexSet", vertexSet);
            var modelPart = new FlexibleModelPart
            {
                IndexCount        = vertexList.Count,
                PrimitiveTopology = FlexibleModelPrimitiveTopology.TriangleList,
                VertexSetIndex    = 0
            };
            var model = new FlexibleModel(ResourceVolatility.Immutable, new[] { vertexSet }, new[] { modelPart }, new Sphere(Vector3.Zero, 50));

            pack.AddSubresource("Model", model);
            pack.MainSubresource = model;

            CheckSuccess(DicomProject.AnalyzerKillDicomAnalyzer(&dicomManager));

            // todo: calculate hash honestly
            var hash     = AssetHashMd5.Random(new Random());
            var fileName = Path.GetFileName(loadInfo.LoadPath);
            var asset    = new Asset(loadInfo.AssetName, pack, AssetStorageType.ReferenceOriginal, hash, loadInfo.ReferencePath, fileName);

            return(AssetLoadResultByLoader.Success(asset));
        }
Example #11
0
 private void SwapBuffers()
 {
     CodingHelper.Swap(ref frontCircleCenters, ref backCircleCenters);
     frontCirclesGrid.Rebuild(frontCircleCenters, numCircles);
 }
Example #12
0
        public void TransferPhi(float deltaT, INavierStokesGrid grid)
        {
            /*
             * Parallel.For(0, Size.Volume(), index =>
             * {
             *  var j = index / Size.Width;
             *  var i = index - j * Size.Width;
             *
             *  if (i < 1 || i >= Size.Width - 1 || j < 1 || j >= Size.Height - 1)
             *      return;
             *
             *  var dpdx = (Phi(i + 1, j) - Phi(i - 1, j)) / (2 * CellSize);
             *  var dpdy = (Phi(i, j + 1) - Phi(i, j - 1)) / (2 * CellSize);
             *  var point = CellSize * (new Vector3(i, j, 0) + new Vector3(0.5f, 0.5f, 0.5f));
             *  var u = grid.GetVelocityAt(point) * deltaT;
             *  var deltaPhi = -u.X * dpdx - u.Y * dpdy;
             *  BackPhi(i, j) = Phi(i, j) + deltaPhi;
             * });*/

            /*
             * for (int j = 1; j < Size.Height - 1; j++)
             * for (int i = 1; i < Size.Width - 1; i++)
             * {
             *  var dpdx = (Phi(i + 1, j) - Phi(i - 1, j)) / (2 * CellSize);
             *  var dpdy = (Phi(i, j + 1) - Phi(i, j - 1)) / (2 * CellSize);
             *  var point = CellSize * (new Vector3(i, j, 0) + new Vector3(0.5f, 0.5f, 0.5f));
             *  var u = grid.GetVelocityAt(point) * deltaT;
             *  var deltaPhi = -u.X * dpdx - u.Y * dpdy;
             *  BackPhi(i, j) = Phi(i, j) + deltaPhi;
             * }*/


            Array.Clear(backPhi, 0, backPhi.Length);
            var halfVector   = new Vector3(0.5f, 0.5f, 0.5f);
            var cornerOffset = CellSize * halfVector;

            Parallel.For(0, Size.Volume(), index =>
            {
                var j = index / Size.Width;
                var i = index - j * Size.Width;

                if (i < 1 || i >= Size.Width - 1 || j < 1 || j >= Size.Height - 1)
                {
                    return;
                }

                var remainingDeltaT = deltaT;
                var point           = CellSize * (new Vector3(i, j, 0) + halfVector);

                while (remainingDeltaT > 0)
                {
                    var v                   = grid.GetVelocityAt(point);
                    var vlen                = v.Length();
                    var localDeltaT         = vlen * remainingDeltaT > CellSize ? CellSize / vlen : remainingDeltaT;
                    var potentialPoint      = point + v * localDeltaT;
                    var potentialCorner     = potentialPoint - cornerOffset;
                    var normPotentialCorner = potentialCorner / CellSize;
                    var npci                = (int)normPotentialCorner.X;
                    var npcj                = (int)normPotentialCorner.Y;
                    if (State(npci, npcj) == NavierStokesCellState.Object)
                    {
                        break;
                    }
                    point            = potentialPoint;
                    remainingDeltaT -= localDeltaT;
                }

                var corner = point - cornerOffset;
                //var centerPoint = new Vector3(Size.Width, Size.Height, 0) * CellSize / 2;
                //while (grid.StateAtPoint(corner) == NavierStokesCellState.Object)
                //{
                //    corner = Vector3.Lerp(corner, centerPoint, 0.05f);
                //}

                var ti        = (int)(corner.X / CellSize);
                var tj        = (int)(corner.Y / CellSize);
                var intCorner = new Vector3(ti, tj, 0) * CellSize;

                var rightVolume = (corner.X - intCorner.X) / CellSize;
                var upVolume    = (corner.Y - intCorner.Y) / CellSize;
                var leftVolume  = 1 - rightVolume;
                var downVolume  = 1 - upVolume;

                var originalMass = Phi(i, j);
                var a00          = originalMass * leftVolume * downVolume;
                var a01          = originalMass * leftVolume * upVolume;
                var a10          = originalMass * rightVolume * downVolume;
                var a11          = originalMass * rightVolume * upVolume;

                lock (backWriteLock)
                {
                    BackPhi(ti, tj)         += a00;
                    BackPhi(ti + 1, tj)     += a10;
                    BackPhi(ti, tj + 1)     += a01;
                    BackPhi(ti + 1, tj + 1) += a11;
                }
            });

            CodingHelper.Swap(ref phi, ref backPhi);
        }