Exemplo n.º 1
0
        public void TestCreateNodes()
        {
            Node n1 = new Node()
            {
                Id = 11,
                Name = "One",
                Paths = new List<Path>()
            };

            Node n2 = new Node()
            {
                Id = 12,
                Name = "Two",
                Paths = new List<Path>()
            };

            Node n3 = new Node()
            {
                Id = 13,
                Name = "Three",
                Paths = new List<Path>()
            };

            Node n4 = new Node()
            {
                Id = 14,
                Name = "Four",
                Paths = new List<Path>()
            };

            n1.Paths.Add(new Path() { OriginNode = n1, DestinationNode = n2 });
            n1.Paths.Add(new Path() { OriginNode = n1, DestinationNode = n4 });

            n2.Paths.Add(new Path() { OriginNode = n2, DestinationNode = n1 });
            n2.Paths.Add(new Path() { OriginNode = n2, DestinationNode = n3 });

            n3.Paths.Add(new Path() { OriginNode = n3, DestinationNode = n4 });

            n4.Paths.Add(new Path() { OriginNode = n4, DestinationNode = n2 });

            DbSet<Node> nodes;
            using (var context = new GraphContext())
            {
                context.Nodes.Add(n1);
                context.Nodes.Add(n2);
                context.Nodes.Add(n3);
                context.Nodes.Add(n4);
                context.SaveChanges();
            }

            using (var context = new GraphContext())
            {
                nodes = context.Nodes;
            }

            Assert.AreEqual(4, nodes.Count());
        }
Exemplo n.º 2
0
        public void Cleanup()
        {
            using (var context = new GraphContext())
            {
                var existingNodes = context.Nodes;

                foreach (var path in context.Paths)
                {
                    context.Paths.Remove(path);
                }
                foreach (var node in existingNodes)
                {
                    context.Nodes.Remove(node);
                }
                context.SaveChanges();
            }
        }
Exemplo n.º 3
0
 private void WritePrimitive(ref GraphContext context)
 {
     switch(context.TypeCode)
     {
         case ObjectTypeCode.Empty:
             WriteEmpty();
             break;
         case ObjectTypeCode.DBNull:
             WriteDBNull();
             break;
         case ObjectTypeCode.Object:
             Guard.Fail("WritePrimitive should not have been called for an Object.");
             break;
         case ObjectTypeCode.Boolean:
             WriteBoolean((bool)context.Graph);
             break;
         case ObjectTypeCode.Char:
             WriteChar((char)context.Graph);
             break;
         case ObjectTypeCode.SByte:
             WriteSByte((sbyte)context.Graph);
             break;
         case ObjectTypeCode.Byte:
             WriteByte((byte)context.Graph);
             break;
         case ObjectTypeCode.Int16:
             WriteInt16((short)context.Graph);
             break;
         case ObjectTypeCode.Int32:
             WriteInt32((int)context.Graph);
             break;
         case ObjectTypeCode.Int64:
             WriteInt64((long)context.Graph);
             break;
         case ObjectTypeCode.UInt16:
             WriteUInt16((ushort)context.Graph);
             break;
         case ObjectTypeCode.UInt32:
             WriteUInt32((uint)context.Graph);
             break;
         case ObjectTypeCode.UInt64:
             WriteUInt64((ulong)context.Graph);
             break;
         case ObjectTypeCode.Single:
             WriteSingle((float)context.Graph);
             break;
         case ObjectTypeCode.Double:
             WriteDouble((double)context.Graph);
             break;
         case ObjectTypeCode.Decimal:
             WriteDecimal((decimal)context.Graph);
             break;
         case ObjectTypeCode.DateTime:
             WriteDateTime((DateTime)context.Graph);
             break;
         case ObjectTypeCode.String:
             WriteString((string)context.Graph);
             break;
         case ObjectTypeCode.TimeSpan:
             WriteTimeSpan((TimeSpan)context.Graph);
             break;
         default:
             throw Guard.ArgumentOutOfRange("context.ObjectTypeCode");
     }
 }
Exemplo n.º 4
0
 private void WriteGraph(ref GraphContext context)
 {
     if(context.TypeCode == ObjectTypeCode.Object)
     {
         AssertGraphHasNotBeenSeen(context.Graph);
         WriteComplex(ref context);
     }
     else
     {
         WritePrimitive(ref context);
     }
 }
Exemplo n.º 5
0
 private void WriteComplex(ref GraphContext context)
 {
     WriteObjectTypeCode(context.TypeCode);
     Output.Write(context.Descriptor.TypeId);
     var serializable = context.Graph as ICustomSerializable;
     if(serializable != null)
     {
         serializable.Write(this);
     }
     else
     {
         Output.Write((byte)context.Descriptor.Properties.Count);
         foreach(var property in context.Descriptor.Properties)
         {
             Output.Write(property.PropertyId);
             WriteDescendant(property.GetValue(context.Graph));
         }
     }
 }
Exemplo n.º 6
0
    public override void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
    {
        registry.ProvideFunction("modulo", s => s.Append(@"
inline float3 modulo(float3 divident, float3 divisor){
float3 positiveDivident = divident % divisor + divisor;
return positiveDivident % divisor;
}

"));


        registry.ProvideFunction("rand3dto1d", s => s.Append(@"

float rand3dTo1d(float3 value, float3 dotDir = float3(12.9898, 78.233, 37.719)){
//make value smaller to avoid artefacts
float3 smallValue = sin(value);
//get scalar value from 3d vector
float random = dot(smallValue, dotDir);
//make value more random by making it bigger and then taking the factional part
random = frac(sin(random) * 143758.5453);
return random;
}

"));


        registry.ProvideFunction("rand3dTo3d", s => s.Append(@"

float3 rand3dTo3d(float3 value){
return float3(
	rand3dTo1d(value, float3(12.989, 78.233, 37.719)),
	rand3dTo1d(value, float3(39.346, 11.135, 83.155)),
	rand3dTo1d(value, float3(73.156, 52.235, 09.151))
);
}

"));


        registry.ProvideFunction("voronoiNoise", s => s.Append(@"
float3 voronoiNoise(float3 value, float3 period){
float3 baseCell = floor(value);

//first pass to find the closest cell
float minDistToCell = 10;
float3 toClosestCell;
float3 closestCell;
[unroll]
for(int x1=-1; x1<=1; x1++){
	[unroll]
	for(int y1=-1; y1<=1; y1++){
		[unroll]
		for(int z1=-1; z1<=1; z1++){
			float3 cell = baseCell + float3(x1, y1, z1);
			float3 tiledCell = modulo(cell, period);
			float3 cellPosition = cell + rand3dTo3d(tiledCell);
			float3 toCell = cellPosition - value;
			float distToCell = length(toCell);
			if(distToCell < minDistToCell){
				minDistToCell = distToCell;
				closestCell = cell;
				toClosestCell = toCell;
			}
		}
	}
}

//second pass to find the distance to the closest edge
float minEdgeDistance = 10;
[unroll]
for(int x2=-1; x2<=1; x2++){
	[unroll]
	for(int y2=-1; y2<=1; y2++){
		[unroll]
		for(int z2=-1; z2<=1; z2++){
			float3 cell = baseCell + float3(x2, y2, z2);
			float3 tiledCell = modulo(cell, period);
			float3 cellPosition = cell + rand3dTo3d(tiledCell);
			float3 toCell = cellPosition - value;

			float3 diffToClosestCell = abs(closestCell - cell);
			bool isClosestCell = diffToClosestCell.x + diffToClosestCell.y + diffToClosestCell.z < 0.1;
			if(!isClosestCell){
				float3 toCenter = (toClosestCell + toCell) * 0.5;
				float3 cellDifference = normalize(toCell - toClosestCell);
				float edgeDistance = dot(toCenter, cellDifference);
				minEdgeDistance = min(minEdgeDistance, edgeDistance);
			}
		}
	}
}

float random = rand3dTo1d(closestCell);
return float3(minDistToCell, random, minEdgeDistance);
}
"));

        base.GenerateNodeFunction(registry, graphContext, generationMode);
    }
 public void each_up()
 {
     registry = new Registry(null);
     Sut = new GraphContext<DummyPersistentObject>(new RegisteredGraph<DummyPersistentObject>(registry));
 }
 public override void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
 {
     base.GenerateNodeFunction(registry, graphContext, generationMode);
 }
Exemplo n.º 9
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
                {
                    HotModuleReplacement = true
                });
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

                routes.MapSpaFallbackRoute(
                    name: "spa-fallback",
                    defaults: new { controller = "Home", action = "Index" });
            });

            Models.Data data;
            using (GraphContext dopravnaSietContext = new GraphContext())
            {
                data = dopravnaSietContext.Data.Where(d => d.Active == true).FirstOrDefault();

                if (data == null && dopravnaSietContext.Data.Count() > 0)
                {
                    data = dopravnaSietContext.Data.First();
                }
            }

            if (data != null)
            {
                long memBefore = GC.GetTotalMemory(true);
                var  watch     = Stopwatch.StartNew();
                PrepareData.PrepareNodesGraph(data);
                watch.Stop();
                long memAfter = GC.GetTotalMemory(true);
                Utils.GraphTime   = watch.Elapsed;
                Utils.GraphMemory = memAfter - memBefore;

                memBefore = GC.GetTotalMemory(true);
                watch     = Stopwatch.StartNew();
                PrepareData.PrepareDisabledMovementGraph();
                watch.Stop();
                memAfter = GC.GetTotalMemory(true);
                Utils.DisabledGraphTime   = Utils.GraphTime + watch.Elapsed;
                Utils.DisabledGraphMemory = Utils.GraphMemory + memAfter - memBefore;

                //TimeSpan time;
                //double lat, lon;
                //Random random = new Random();
                //double maximumLat = data.MaxLat, minimumLat = data.MinLat;
                //double maximumLon = data.MaxLon, minimumLon = data.MinLon;
                //for (int i = 0; i < 1000; i++)
                //{
                //    lat = random.NextDouble() * (maximumLat - minimumLat) + minimumLat;
                //    lon = random.NextDouble() * (maximumLon - minimumLon) + minimumLon;
                //    watch = Stopwatch.StartNew();
                //    var startNode = PrepareData.NodesGraph.OrderBy(n1 => (Utils.Distance(n1.Key.Lat,
                //                                                            n1.Key.Lon,
                //                                                            lat,
                //                                                            lon)
                //                                                            )).First();
                //    watch.Stop();
                //    time += watch.Elapsed;
                //}
                //var timeAverage = time / 1000;

                //System.Device.Location.GeoCoordinate coord;
                //for (int i = 0; i < 1000; i++)
                //{
                //    lat = random.NextDouble() * (maximumLat - minimumLat) + minimumLat;
                //    lon = random.NextDouble() * (maximumLon - minimumLon) + minimumLon;
                //    coord = new System.Device.Location.GeoCoordinate(lat, lon);
                //    watch = Stopwatch.StartNew();
                //    var startNode = PrepareData.NodesGraph.Select(x => new System.Device.Location.GeoCoordinate(x.Key.Lat, x.Key.Lon))
                //                               .OrderBy(x => x.GetDistanceTo(coord))
                //                               .First();
                //    watch.Stop();
                //    time += watch.Elapsed;
                //}
                //var timeAverageOrdered = time / 1000;

                //        int opakovani = 10;
                //        int algoritmus = 0;
                //        TimeSpan time;
                //        Zakladny zakladny = new Zakladny();
                //        Dijkster dijkster = new Dijkster();
                //        AStar astar = new AStar();
                //        LabelCorrect labelCorrect = new LabelCorrect();
                //        LabelSet labelSet = new LabelSet();
                //        DuplexDijkster duplexDijkster = new DuplexDijkster();
                //        watch = Stopwatch.StartNew();
                //        Random random = new Random();
                //        NodeGraphDTO[] startNodes = new NodeGraphDTO[opakovani];
                //        NodeGraphDTO[] endNodes = new NodeGraphDTO[opakovani];
                //        List<RoutesDTO> routesAll = new List<RoutesDTO>(6);

                //        for (int i = 0; i < opakovani; i++)
                //        {
                //            startNodes[i] = PrepareData.NodesGraph.Values.ElementAt(random.Next(PrepareData.NodesGraph.Count));
                //            endNodes[i] = PrepareData.NodesGraph.Values.ElementAt(random.Next(PrepareData.NodesGraph.Count));
                //        }

                //        for (int j = 0; j < 6; j++)
                //        {
                //            RoutesDTO routes = new RoutesDTO();
                //            for (int i = 0; i < opakovani; i++)
                //            {
                //                PrepareData.PrepareNodesGraph();
                //                switch (j)
                //                {
                //                    case 0:
                //                        PrepareData.PutStartEnd(startNodes[i], endNodes[i]);
                //                        watch.Restart();
                //                        var n = zakladny.CalculateShortestPath(startNodes[i], endNodes[i], PrepareData.NodesGraph);
                //                        watch.Stop();
                //                        time = watch.Elapsed;
                //                        AfterCalculateShortestPath(n, time, routes);
                //                        PrepareData.RemoveStartEnd(startNodes[i], endNodes[i]);
                //                        break;
                //                    case 1:
                //                        PrepareData.PutStartEnd(startNodes[i], endNodes[i]);
                //                        watch.Restart();
                //                        n = dijkster.CalculateShortestPath(startNodes[i], endNodes[i]);
                //                        watch.Stop();
                //                        time = watch.Elapsed;
                //                        AfterCalculateShortestPath(n, time, routes);
                //                        PrepareData.RemoveStartEnd(startNodes[i], endNodes[i]);
                //                        break;
                //                    case 2:
                //                        PrepareData.PutStartEnd(startNodes[i], endNodes[i]);
                //                        watch.Restart();
                //                        n = astar.CalculateShortestPath(startNodes[i], endNodes[i]);
                //                        watch.Stop();
                //                        time = watch.Elapsed;
                //                        var a = routes.Route.Last;
                //                        AfterCalculateShortestPath(n, time, routes);
                //                        PrepareData.RemoveStartEnd(startNodes[i], endNodes[i]);
                //                        break;
                //                    case 3:
                //                        PrepareData.PutStartEnd(startNodes[i], endNodes[i]);
                //                        watch.Restart();
                //                        n = labelSet.CalculateShortestPath(startNodes[i], endNodes[i]);
                //                        watch.Stop();
                //                        time = watch.Elapsed;
                //                        AfterCalculateShortestPath(n, time, routes);
                //                        PrepareData.RemoveStartEnd(startNodes[i], endNodes[i]);
                //                        break;
                //                    case 4:
                //                        PrepareData.PutStartEnd(startNodes[i], endNodes[i]);
                //                        watch.Restart();
                //                        n = labelCorrect.CalculateShortestPath(startNodes[i], endNodes[i]);
                //                        watch.Stop();
                //                        time = watch.Elapsed;
                //                        AfterCalculateShortestPath(n, time, routes);
                //                        PrepareData.RemoveStartEnd(startNodes[i], endNodes[i]);
                //                        break;
                //                    case 5:
                //                        PrepareData.PutStartEnd(startNodes[i], endNodes[i]);
                //                        watch.Restart();
                //                        n = duplexDijkster.CalculateShortestPath(startNodes[i], endNodes[i]);
                //                        watch.Stop();
                //                        time = watch.Elapsed;
                //                        AfterCalculateShortestPathDuplex(n, time, routes);
                //                        PrepareData.RemoveStartEnd(startNodes[i], endNodes[i]);
                //                        break;
                //                }
                //            }
                //            routesAll.Add(routes);
                //        }

                //        double[] PocetHranCesty = new double[6];
                //        double[] PocetSpracovanychVrcholov = new double[6];
                //        double[] DlzkaCesty = new double[6];
                //        TimeSpan[] CasVypoctu = new TimeSpan[6];
                //        algoritmus = 0;
                //        foreach (RoutesDTO r in routesAll)
                //        {
                //            opakovani = r.Route.Count == 0 ? opakovani : r.Route.Count;
                //            long PocetHranCestyA = 0;
                //            long PocetSpracovanychVrcholovA = 0;
                //            double DlzkaCestyA = 0;
                //            TimeSpan CasVypoctuA = new TimeSpan();
                //            foreach (RouteDTO route in r.Route)
                //            {
                //                PocetHranCestyA += route.PocetHranCesty;
                //                PocetSpracovanychVrcholovA += route.PocetSpracovanychVrcholov;
                //                DlzkaCestyA += route.DlzkaCesty;
                //                CasVypoctuA += route.CasVypoctu;
                //            }
                //            PocetHranCesty[algoritmus] = (double) PocetHranCestyA / opakovani;
                //            PocetSpracovanychVrcholov[algoritmus] = (double) PocetSpracovanychVrcholovA / opakovani;
                //            DlzkaCesty[algoritmus] = DlzkaCestyA / opakovani;
                //            CasVypoctu[algoritmus] = CasVypoctuA / opakovani;
                //            algoritmus++;
                //        }
                //    }
                //}

                //private void AfterCalculateShortestPath(NodeGraphDTO nodeCon, TimeSpan time, RoutesDTO routes)
                //{
                //    if (nodeCon == null)
                //        return;

                //    NodeGraphDTO node = nodeCon;
                //    LinkedList<NodeLocationDTO> nodeRoute = new LinkedList<NodeLocationDTO>();
                //    while (node != null)
                //    {
                //        nodeRoute.AddLast(new NodeLocationDTO()
                //        {
                //            Lat = node.Node.Lat,
                //            Lon = node.Node.Lon
                //        });
                //        node = node.PreviousNode;
                //    }

                //    RouteDTO route = new RouteDTO()
                //    {
                //        PocetHranCesty = nodeRoute.Count,
                //        PocetSpracovanychVrcholov = Utils.PocetSpracovanychVrcholov,
                //        DlzkaCesty = nodeCon.CurrentDistance / 1000,
                //        CasVypoctu = time
                //    };

                //    routes.Route.AddLast(route);
                //}

                //private void AfterCalculateShortestPathDuplex(NodeGraphDTO nodeCon, TimeSpan time, RoutesDTO routes)
                //{
                //    if (nodeCon == null)
                //        return;

                //    NodeGraphDTO node = nodeCon;
                //    LinkedList<NodeLocationDTO> nodeRoute = new LinkedList<NodeLocationDTO>();
                //    while (node != null)
                //    {
                //        nodeRoute.AddLast(new NodeLocationDTO()
                //        {
                //            Lat = node.Node.Lat,
                //            Lon = node.Node.Lon
                //        });
                //        node = node.PreviousNode;
                //    }

                //    node = nodeCon != null ? nodeCon.PreviousNodeR : null;
                //    while (node != null)
                //    {
                //        nodeRoute.AddFirst(new NodeLocationDTO()
                //        {
                //            Lat = node.Node.Lat,
                //            Lon = node.Node.Lon
                //        });
                //        node = node.PreviousNodeR;
                //    }

                //    RouteDTO route = new RouteDTO()
                //    {
                //        PocetHranCesty = nodeRoute.Count,
                //        PocetSpracovanychVrcholov = Utils.PocetSpracovanychVrcholov,
                //        DlzkaCesty = nodeCon.CurrentDistance / 1000,
                //        CasVypoctu = time
                //    };

                //    routes.Route.AddLast(route);
            }
        }
Exemplo n.º 10
0
    public override void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
    {
        isPreview = generationMode == GenerationMode.Preview;

        base.GenerateNodeFunction(registry, graphContext, generationMode);
    }
Exemplo n.º 11
0
 public TaskRepository(GraphContext context) : base(context)
 {
 }
Exemplo n.º 12
0
 public void Tick(float dt, GraphContext context)
 {
 }
Exemplo n.º 13
0
 public void Initialize(GraphContext context)
 {
 }
Exemplo n.º 14
0
    public override void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
    {
        registry.ProvideFunction("mod289", s => s.Append(@"
inline float3 mod289(float3 x)
{
	return x - floor(x * (1.0 / 289.0)) * 289.0;
}"));
        registry.ProvideFunction("mod289", s => s.Append(@"
inline float4 mod289(float4 x)
{
	return x - floor(x * (1.0 / 289.0)) * 289.0;
}"));

        registry.ProvideFunction("permute", s => s.Append(@"
inline float4 permute(float4 x)
{
	return mod289(((x * 34.0) + 1.0) * x);
}"));
        registry.ProvideFunction("permute", s => s.Append(@"
inline float3 permute(float3 x)
{
	return fmod(((x * 34.0) + 1.0) * x, 289.0);
}"));

        registry.ProvideFunction("taylorInvSqrt", s => s.Append(@"
inline float4 taylorInvSqrt(float4 r)
{
	return 1.79284291400159 - 0.85373472095314 * r;
}"));

        registry.ProvideFunction("snoise", s => s.Append(@"
float snoise(float3 v)
{
	const float2 C = float2(1.0 / 6.0, 1.0 / 3.0);
	const float4 D = float4(0.0, 0.5, 1.0, 2.0);

	float3 i  = floor(v + dot(v, C.yyy));
	float3 x0 = v   - i + dot(i, C.xxx); 
	
	float3 g = step(x0.yzx, x0.xyz);
	float3 l = 1.0 - g;
	float3 i1 = min(g.xyz, l.zxy);
	float3 i2 = max(g.xyz, l.zxy);

	//     x0 = x0 - 0. + 0.0 * C 
	float3 x1 = x0 - i1 + 1.0 * C.xxx; 
	float3 x2 = x0 - i2 + 2.0 * C.xxx; 
	float3 x3 = x0 - 1. + 3.0 * C.xxx; 

	i = mod289(i);
	float4 p = permute(permute(permute(
		  i.z + float4(0.0, i1.z, i2.z, 1.0))
		+ i.y + float4(0.0, i1.y, i2.y, 1.0))
		+ i.x + float4(0.0, i1.x, i2.x, 1.0));

	float  n_ = 0.142857142857; // 1.0 / 7.0
	float3 ns = n_ * D.wyz - D.xzx;

	float4 j = p - 49.0 * floor(p * ns.z * ns.z);	// fmod(p, 7*7)

	float4 x_ = floor(j * ns.z);
	float4 y_ = floor(j - 7.0 * x_); // fmod(j, N)

	float4 x = x_ * ns.x + ns.yyyy;
	float4 y = y_ * ns.x + ns.yyyy;
	float4 h = 1.0 - abs(x) - abs(y);

	float4 b0 = float4(x.xy, y.xy);
	float4 b1 = float4(x.zw, y.zw);

	float4 s0 = floor(b0) * 2.0 + 1.0;
	float4 s1 = floor(b1) * 2.0 + 1.0;
	float4 sh = -step(h, float4(0.0, 0.0, 0.0, 0.0));

	float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
	float4 a1 = b1.xzyw + s1.xzyw * sh.zzww;

	float3 p0 = float3(a0.xy, h.x);
	float3 p1 = float3(a0.zw, h.y);
	float3 p2 = float3(a1.xy, h.z);
	float3 p3 = float3(a1.zw, h.w);

	float4 norm = taylorInvSqrt(float4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
	p0 *= norm.x;
	p1 *= norm.y;
	p2 *= norm.z;
	p3 *= norm.w;

	float4 m = max(0.6 - float4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);
	m = m * m;

	return 42.0 * dot(m * m, float4(dot(p0, x0), dot(p1, x1),
		dot(p2, x2), dot(p3, x3)));
}"));

        registry.ProvideFunction("curlNoise", s => s.Append(@"
float3 curlNoise(float3 coord)
{
    float3 dx = float3(EPSILON, 0.0, 0.0);
    float3 dy = float3(0.0, EPSILON, 0.0);
    float3 dz = float3(0.0, 0.0, EPSILON);

    float3 dpdx0 = simplexNoise(coord - dx);
    float3 dpdx1 = simplexNoise(coord + dx);
    float3 dpdy0 = simplexNoise(coord - dy);
    float3 dpdy1 = simplexNoise(coord + dy);
    float3 dpdz0 = simplexNoise(coord - dz);
    float3 dpdz1 = simplexNoise(coord + dz);

    float x = dpdy1.z - dpdy0.z + dpdz1.y - dpdz0.y;
    float y = dpdz1.x - dpdz0.x + dpdx1.z - dpdx0.z;
    float z = dpdx1.y - dpdx0.y + dpdy1.x - dpdy0.x;

    return float3(x, y, z) / EPSILON * 2.0;
}
"));

        base.GenerateNodeFunction(registry, graphContext, generationMode);
    }