Beispiel #1
0
        static int isea_ptdi(ref isea_dgg g, int tri, isea_pt pt, out isea_pt di)
        {
            isea_pt v    = pt;
            int     quad = isea_ptdd(tri, ref v);

            quad = isea_dddi(ref g, quad, v, out di);
            return(quad);
        }
Beispiel #2
0
        // convert projected triangle coords to quad xy coords, return quad number
        static int isea_ptdd(int tri, ref isea_pt pt)
        {
            bool downtri = (((tri - 1) / 5) % 2 == 1);
            int  quad    = ((tri - 1) % 5) + ((tri - 1) / 10) * 5 + 1;

            isea_rotate(ref pt, downtri?240.0:60.0);
            if (downtri)
            {
                pt.x += 0.5;
                // pt->y += cos(30.0 * Math.PI / 180.0);
                pt.y += 0.86602540378443864672;
            }
            return(quad);
        }
Beispiel #3
0
        static int isea_tri_plane(int tri, ref isea_pt pt, double radius)
        {
            isea_pt tc;             // center of triangle

            if (((tri - 1) / 5) % 2 == 1)
            {
                isea_rotate(ref pt, 180.0);
            }

            tc    = isea_triangle_xy(tri);
            tc.x *= radius;
            tc.y *= radius;
            pt.x += tc.x;
            pt.y += tc.y;

            return(tri);
        }
Beispiel #4
0
        static int isea_transform(ref isea_dgg g, isea_geo @in, out isea_pt @out)
        {
            isea_geo pole;

            pole.lat = g.o_lat;
            pole.lon = g.o_lon;

            isea_geo i = isea_ctran(ref pole, @in, g.o_az);

            int tri = isea_snyder_forward(i, out @out);

            @out.x    *= g.radius;
            @out.y    *= g.radius;
            g.triangle = tri;

            return(tri);
        }
Beispiel #5
0
        // Proj 4 integration code follows

        // spheroid
        XY s_forward(LP lp)
        {
            XY xy;

            xy.x = xy.y = 0;

            isea_geo @in;

            @in.lon = lp.lam;
            @in.lat = lp.phi;

            isea_pt @out = isea_forward(dgg, @in);

            xy.x = @out.x;
            xy.y = @out.y;

            return(xy);
        }
Beispiel #6
0
        static void isea_rotate(ref isea_pt pt, double degrees)
        {
            double rad = -degrees * Math.PI / 180.0;

            while (rad >= 2.0 * Math.PI)
            {
                rad -= 2.0 * Math.PI;
            }
            while (rad <= -2.0 * Math.PI)
            {
                rad += 2.0 * Math.PI;
            }

            double x = pt.x * Math.Cos(rad) + pt.y * Math.Sin(rad);
            double y = -pt.x * Math.Sin(rad) + pt.y * Math.Cos(rad);

            pt.x = x;
            pt.y = y;
        }
Beispiel #7
0
        // q2di to seqnum
        static int isea_disn(ref isea_dgg g, int quad, isea_pt di)
        {
            if (quad == 0)
            {
                g.serial = 1;
                return(1);
            }

            // hexes in a quad
            int hexes = (int)(Math.Pow(g.aperture, g.resolution) + 0.5);

            if (quad == 11)
            {
                g.serial = (ulong)(1 + 10 * hexes + 1);
                return((int)g.serial);
            }

            int sn;

            if (g.aperture == 3 && g.resolution % 2 == 1)
            {
                int height = (int)(Math.Pow(g.aperture, (g.resolution - 1) / 2.0));
                sn  = ((int)di.x) * height;
                sn += ((int)di.y) / height;
                sn += (quad - 1) * hexes;
                sn += 2;
            }
            else
            {
                int sidelength = (int)(Math.Pow(g.aperture, g.resolution / 2.0) + 0.5);
                sn = (int)((quad - 1) * hexes + sidelength * di.x + di.y + 2);
            }

            g.serial = (ulong)sn;
            return(sn);
        }
Beispiel #8
0
        // coord needs to be in radians
        static int isea_snyder_forward(isea_geo ll, out isea_pt @out)
        {
            // TODO by locality of reference, start by trying the same triangle
            // as last time

            // TODO put these constants in as radians to begin with
            snyder_constants c=constants[(int)snyder_polyhedron.SNYDER_POLY_ICOSAHEDRON];

            // plane angle between radius vector to center and adjacent edge of
            // plane polygon
            double theta=c.theta*DEG2RAD;

            // spherical distance from center of polygon face to any of its
            // vertexes on the globe
            double g=c.g*DEG2RAD;

            // spherical angle between radius vector to center and adjacent edge
            // of spherical polygon on the globe
            double G=c.G*DEG2RAD;

            for(int i=1; i<=20; i++)
            {
                double z;
                isea_geo center;

                center=icostriangles[i];

                // step 1
                z=Math.Acos(Math.Sin(center.lat)*Math.Sin(ll.lat)+Math.Cos(center.lat)*Math.Cos(ll.lat)*Math.Cos(ll.lon-center.lon));

                // not on this triangle
                if(z>g+0.000005) continue; // TODO DBL_EPSILON

                double Az=sph_azimuth(center.lon, center.lat, ll.lon, ll.lat);

                // step 2

                // This calculates "some" vertex coordinate
                double az_offset=az_adjustment(i);

                Az-=az_offset;

                // TODO I don't know why we do this. It's not in snyder
                // maybe because we should have picked a better vertex
                if(Az<0.0) Az+=2.0*Math.PI;

                // adjust Az for the point to fall within the range of 0 to
                // 2(90 - theta) or 60 degrees for the hexagon, by
                // and therefore 120 degrees for the triangle
                // of the icosahedron
                // subtracting or adding multiples of 60 degrees to Az and
                // recording the amount of adjustment
                int Az_adjust_multiples=0; // how many multiples of 60 degrees we adjust the azimuth

                while(Az<0.0)
                {
                    Az+=DEG120;
                    Az_adjust_multiples--;
                }

                while(Az>DEG120+double.Epsilon)
                {
                    Az-=DEG120;
                    Az_adjust_multiples++;
                }

                // step 3
                double cot_theta=1.0/Math.Tan(theta);
                double tan_g=Math.Tan(g);	// TODO this is a constant

                // Calculate q from eq 9.
                // TODO cot_theta is cot(30)
                double q=Math.Atan2(tan_g, Math.Cos(Az)+Math.Sin(Az)*cot_theta);

                // not in this triangle
                if(z>q+0.000005) continue;
                // step 4

                // Apply equations 5-8 and 10-12 in order

                // eq 5
                // Rprime = 0.9449322893 * R;
                // R' in the paper is for the truncated
                double Rprime=0.91038328153090290025;

                // eq 6
                double H=Math.Acos(Math.Sin(Az)*Math.Sin(G)*Math.Cos(g)-Math.Cos(Az)*Math.Cos(G));

                // eq 7
                // Ag = (Az + G + H - DEG180) * M_PI * R * R / DEG180;
                double Ag=Az+G+H-DEG180;

                // eq 8
                double Azprime=Math.Atan2(2.0*Ag, Rprime*Rprime*tan_g*tan_g-2.0*Ag*cot_theta);

                // eq 10
                // cot(theta) = 1.73205080756887729355
                double dprime=Rprime*tan_g/(Math.Cos(Azprime)+Math.Sin(Azprime)*cot_theta);

                // eq 11
                double f=dprime/(2.0*Rprime*Math.Sin(q/2.0));

                // eq 12
                double rho=2.0*Rprime*f*Math.Sin(z/2.0);

                // add back the same 60 degree multiple adjustment from step
                // 2 to Azprime
                Azprime+=DEG120*Az_adjust_multiples;

                // calculate rectangular coordinates
                double x=rho*Math.Sin(Azprime);
                double y=rho*Math.Cos(Azprime);

                // TODO
                // translate coordinates to the origin for the particular
                // hexagon on the flattened polyhedral map plot
                @out.x=x;
                @out.y=y;

                return i;
            }

            // should be impossible, this implies that the coordinate is not on
            // any triangle

            //fprintf(stderr, "impossible transform: %f %f is not on any triangle\n",
            //    ll.lon*RAD2DEG, ll.lat*RAD2DEG);

            throw new Exception();
        }
Beispiel #9
0
 static int isea_ptdi(ref isea_dgg g, int tri, isea_pt pt, out isea_pt di)
 {
     isea_pt v=pt;
     int quad=isea_ptdd(tri, ref v);
     quad=isea_dddi(ref g, quad, v, out di);
     return quad;
 }
Beispiel #10
0
        static void isea_rotate(ref isea_pt pt, double degrees)
        {
            double rad=-degrees*Math.PI/180.0;
            while(rad>=2.0*Math.PI) rad-=2.0*Math.PI;
            while(rad<=-2.0*Math.PI) rad+=2.0*Math.PI;

            double x=pt.x*Math.Cos(rad)+pt.y*Math.Sin(rad);
            double y=-pt.x*Math.Sin(rad)+pt.y*Math.Cos(rad);

            pt.x=x;
            pt.y=y;
        }
Beispiel #11
0
        // TODO just encode the quad in the d or i coordinate
        // quad is 0-11, which can be four bits.
        // d' = d << 4 + q, d = d' >> 4, q = d' & 0xf
        // convert a q2di to global hex coord
        static int isea_hex(ref isea_dgg g, int tri, isea_pt pt, out isea_pt hex)
        {
            isea_pt v;
            int quad=isea_ptdi(ref g, tri, pt, out v);

            hex.x=((int)v.x<<4)+quad;
            hex.y=v.y;

            return 1;

            // silence the compiler
            #if false
            double d=v.x;
            double i=v.y;

            // Aperture 3 odd resolutions
            if(g.aperture==3&&g.resolution%2!=0)
            {
                int offset=(int)(Math.Pow(3.0, g.resolution-1)+0.5);

                d+=offset*((g.quad-1)%5);
                i+=offset*((g.quad-1)%5);

                if(quad==0)
                {
                    d=0;
                    i=offset;
                }
                else if(quad==11)
                {
                    d=2*offset;
                    i=0;
                }
                else if(quad>5)
                {
                    d+=offset;
                }

                double x=(2*d-i)/3;
                double y=(2*i-d)/3;

                hex.x=x+offset/3;
                hex.y=y+2*offset/3;

                return 1;
            }

            // aperture 3 even resolutions and aperture 4
            double sidelength=(int)(Math.Pow(g.aperture, g.resolution/2.0)+0.5);
            if(g.quad==0)
            {
                hex.x=0;
                hex.y=sidelength;
            }
            else if(g.quad==11)
            {
                hex.x=sidelength*2;
                hex.y=0;
            }
            else
            {
                hex.x=d+sidelength*((g.quad-1)%5);
                if(g.quad>5) hex.x+=sidelength;
                hex.y=i+sidelength*((g.quad-1)%5);
            }

            return 1;
            #endif
        }
Beispiel #12
0
        // convert projected triangle coords to quad xy coords, return quad number
        static int isea_ptdd(int tri, ref isea_pt pt)
        {
            bool downtri=(((tri-1)/5)%2==1);
            int quad=((tri-1)%5)+((tri-1)/10)*5+1;

            isea_rotate(ref pt, downtri?240.0:60.0);
            if(downtri)
            {
                pt.x+=0.5;
                // pt->y += cos(30.0 * Math.PI / 180.0);
                pt.y+=0.86602540378443864672;
            }
            return quad;
        }
Beispiel #13
0
        static int isea_dddi_ap3odd(ref isea_dgg g, int quad, isea_pt pt, out isea_pt di)
        {
            // This is the number of hexes from apex to base of a triangle
            double sidelength=(Math.Pow(2.0, g.resolution)+1.0)/2.0; // in hexes

            // apex to base is cos(30deg)
            double hexwidth=Math.Cos(Math.PI/6.0)/sidelength;

            // TODO I think sidelength is always x.5, so
            // (int)sidelength * 2 + 1 might be just as good
            int maxcoord=(int)(sidelength*2.0+0.5);

            isea_pt v=pt;
            hex h;
            h.z=0;
            hexbin2(hexwidth, v.x, v.y, out h.x, out h.y);
            h.iso=false;
            hex_iso(ref h);

            int d=h.x-h.z;
            int i=h.x+h.y+h.y;

            // you want to test for max coords for the next quad in the same
            // "row" first to get the case where both are max
            if(quad<=5)
            {
                if(d==0&&i==maxcoord)
                {
                    // north pole
                    quad=0;
                    d=0;
                    i=0;
                }
                else if(i==maxcoord)
                {
                    // upper right in next quad
                    quad+=1;
                    if(quad==6) quad=1;
                    i=maxcoord-d;
                    d=0;
                }
                else if(d==maxcoord)
                {
                    // lower right in quad to lower right
                    quad+=5;
                    d=0;
                }
            }
            else if(quad>=6)
            {
                if(i==0&&d==maxcoord)
                {
                    // south pole
                    quad=11;
                    d=0;
                    i=0;
                }
                else if(d==maxcoord)
                {
                    // lower right in next quad
                    quad+=1;
                    if(quad==11) quad=6;
                    d=maxcoord-i;
                    i=0;
                }
                else if(i==maxcoord)
                {
                    // upper right in quad to upper right
                    quad=(quad-4)%5;
                    i=0;
                }
            }

            di.x=d;
            di.y=i;

            g.quad=quad;
            return quad;
        }
Beispiel #14
0
        // q2di to seqnum
        static int isea_disn(ref isea_dgg g, int quad, isea_pt di)
        {
            if(quad==0)
            {
                g.serial=1;
                return 1;
            }

            // hexes in a quad
            int hexes=(int)(Math.Pow(g.aperture, g.resolution)+0.5);
            if(quad==11)
            {
                g.serial=(ulong)(1+10*hexes+1);
                return (int)g.serial;
            }

            int sn;
            if(g.aperture==3&&g.resolution%2==1)
            {
                int height=(int)(Math.Pow(g.aperture, (g.resolution-1)/2.0));
                sn=((int)di.x)*height;
                sn+=((int)di.y)/height;
                sn+=(quad-1)*hexes;
                sn+=2;
            }
            else
            {
                int sidelength=(int)(Math.Pow(g.aperture, g.resolution/2.0)+0.5);
                sn=(int)((quad-1)*hexes+sidelength*di.x+di.y+2);
            }

            g.serial=(ulong)sn;
            return sn;
        }
Beispiel #15
0
        static int isea_dddi(ref isea_dgg g, int quad, isea_pt pt, out isea_pt di)
        {
            if(g.aperture==3&&g.resolution%2!=0)
                return isea_dddi_ap3odd(ref g, quad, pt, out di);

            // todo might want to do this as an iterated loop
            int sidelength;	// in hexes
            if(g.aperture>0) sidelength=(int)(Math.Pow(g.aperture, g.resolution/2.0)+0.5);
            else sidelength=g.resolution;

            double hexwidth=1.0/sidelength;

            isea_pt v=pt;
            hex h;
            h.z=0;
            isea_rotate(ref v, -30.0);
            hexbin2(hexwidth, v.x, v.y, out h.x, out h.y);
            h.iso=false;
            hex_iso(ref h);

            // we may actually be on another quad
            if(quad<=5)
            {
                if(h.x==0&&h.z==-sidelength)
                {
                    // north pole
                    quad=0;
                    h.z=0;
                    h.y=0;
                    h.x=0;
                }
                else if(h.z==-sidelength)
                {
                    quad=quad+1;
                    if(quad==6) quad=1;
                    h.y=sidelength-h.x;
                    h.z=h.x-sidelength;
                    h.x=0;
                }
                else if(h.x==sidelength)
                {
                    quad+=5;
                    h.y=-h.z;
                    h.x=0;
                }
            }
            else if(quad>=6)
            {
                if(h.z==0&&h.x==sidelength)
                {
                    // south pole
                    quad=11;
                    h.x=0;
                    h.y=0;
                    h.z=0;
                }
                else if(h.x==sidelength)
                {
                    quad=quad+1;
                    if(quad==11) quad=6;
                    h.x=h.y+sidelength;
                    h.y=0;
                    h.z=-h.x;
                }
                else if(h.y==-sidelength)
                {
                    quad-=4;
                    h.y=0;
                    h.z=-h.x;
                }
            }
            di.x=h.x;
            di.y=-h.z;

            g.quad=quad;
            return quad;
        }
Beispiel #16
0
        // coord needs to be in radians
        static int isea_snyder_forward(isea_geo ll, out isea_pt @out)
        {
            // TODO by locality of reference, start by trying the same triangle
            // as last time

            // TODO put these constants in as radians to begin with
            snyder_constants c = constants[(int)snyder_polyhedron.SNYDER_POLY_ICOSAHEDRON];

            // plane angle between radius vector to center and adjacent edge of
            // plane polygon
            double theta = c.theta * DEG2RAD;

            // spherical distance from center of polygon face to any of its
            // vertexes on the globe
            double g = c.g * DEG2RAD;

            // spherical angle between radius vector to center and adjacent edge
            // of spherical polygon on the globe
            double G = c.G * DEG2RAD;

            for (int i = 1; i <= 20; i++)
            {
                double   z;
                isea_geo center;

                center = icostriangles[i];

                // step 1
                z = Math.Acos(Math.Sin(center.lat) * Math.Sin(ll.lat) + Math.Cos(center.lat) * Math.Cos(ll.lat) * Math.Cos(ll.lon - center.lon));

                // not on this triangle
                if (z > g + 0.000005)
                {
                    continue;                              // TODO DBL_EPSILON
                }
                double Az = sph_azimuth(center.lon, center.lat, ll.lon, ll.lat);

                // step 2

                // This calculates "some" vertex coordinate
                double az_offset = az_adjustment(i);

                Az -= az_offset;

                // TODO I don't know why we do this. It's not in snyder
                // maybe because we should have picked a better vertex
                if (Az < 0.0)
                {
                    Az += 2.0 * Math.PI;
                }

                // adjust Az for the point to fall within the range of 0 to
                // 2(90 - theta) or 60 degrees for the hexagon, by
                // and therefore 120 degrees for the triangle
                // of the icosahedron
                // subtracting or adding multiples of 60 degrees to Az and
                // recording the amount of adjustment
                int Az_adjust_multiples = 0;               // how many multiples of 60 degrees we adjust the azimuth

                while (Az < 0.0)
                {
                    Az += DEG120;
                    Az_adjust_multiples--;
                }

                while (Az > DEG120 + double.Epsilon)
                {
                    Az -= DEG120;
                    Az_adjust_multiples++;
                }

                // step 3
                double cot_theta = 1.0 / Math.Tan(theta);
                double tan_g     = Math.Tan(g);                 // TODO this is a constant

                // Calculate q from eq 9.
                // TODO cot_theta is cot(30)
                double q = Math.Atan2(tan_g, Math.Cos(Az) + Math.Sin(Az) * cot_theta);

                // not in this triangle
                if (z > q + 0.000005)
                {
                    continue;
                }
                // step 4

                // Apply equations 5-8 and 10-12 in order

                // eq 5
                // Rprime = 0.9449322893 * R;
                // R' in the paper is for the truncated
                double Rprime = 0.91038328153090290025;

                // eq 6
                double H = Math.Acos(Math.Sin(Az) * Math.Sin(G) * Math.Cos(g) - Math.Cos(Az) * Math.Cos(G));

                // eq 7
                // Ag = (Az + G + H - DEG180) * M_PI * R * R / DEG180;
                double Ag = Az + G + H - DEG180;

                // eq 8
                double Azprime = Math.Atan2(2.0 * Ag, Rprime * Rprime * tan_g * tan_g - 2.0 * Ag * cot_theta);

                // eq 10
                // cot(theta) = 1.73205080756887729355
                double dprime = Rprime * tan_g / (Math.Cos(Azprime) + Math.Sin(Azprime) * cot_theta);

                // eq 11
                double f = dprime / (2.0 * Rprime * Math.Sin(q / 2.0));

                // eq 12
                double rho = 2.0 * Rprime * f * Math.Sin(z / 2.0);

                // add back the same 60 degree multiple adjustment from step
                // 2 to Azprime
                Azprime += DEG120 * Az_adjust_multiples;

                // calculate rectangular coordinates
                double x = rho * Math.Sin(Azprime);
                double y = rho * Math.Cos(Azprime);

                // TODO
                // translate coordinates to the origin for the particular
                // hexagon on the flattened polyhedral map plot
                @out.x = x;
                @out.y = y;

                return(i);
            }

            // should be impossible, this implies that the coordinate is not on
            // any triangle

            //fprintf(stderr, "impossible transform: %f %f is not on any triangle\n",
            //    ll.lon*RAD2DEG, ll.lat*RAD2DEG);

            throw new Exception();
        }
Beispiel #17
0
        static int isea_transform(ref isea_dgg g, isea_geo @in, out isea_pt @out)
        {
            isea_geo pole;
            pole.lat=g.o_lat;
            pole.lon=g.o_lon;

            isea_geo i=isea_ctran(ref pole, @in, g.o_az);

            int tri=isea_snyder_forward(i, out @out);
            @out.x*=g.radius;
            @out.y*=g.radius;
            g.triangle=tri;

            return tri;
        }
Beispiel #18
0
        static int isea_dddi(ref isea_dgg g, int quad, isea_pt pt, out isea_pt di)
        {
            if (g.aperture == 3 && g.resolution % 2 != 0)
            {
                return(isea_dddi_ap3odd(ref g, quad, pt, out di));
            }

            // todo might want to do this as an iterated loop
            int sidelength;             // in hexes

            if (g.aperture > 0)
            {
                sidelength = (int)(Math.Pow(g.aperture, g.resolution / 2.0) + 0.5);
            }
            else
            {
                sidelength = g.resolution;
            }

            double hexwidth = 1.0 / sidelength;

            isea_pt v = pt;
            hex     h;

            h.z = 0;
            isea_rotate(ref v, -30.0);
            hexbin2(hexwidth, v.x, v.y, out h.x, out h.y);
            h.iso = false;
            hex_iso(ref h);

            // we may actually be on another quad
            if (quad <= 5)
            {
                if (h.x == 0 && h.z == -sidelength)
                {
                    // north pole
                    quad = 0;
                    h.z  = 0;
                    h.y  = 0;
                    h.x  = 0;
                }
                else if (h.z == -sidelength)
                {
                    quad = quad + 1;
                    if (quad == 6)
                    {
                        quad = 1;
                    }
                    h.y = sidelength - h.x;
                    h.z = h.x - sidelength;
                    h.x = 0;
                }
                else if (h.x == sidelength)
                {
                    quad += 5;
                    h.y   = -h.z;
                    h.x   = 0;
                }
            }
            else if (quad >= 6)
            {
                if (h.z == 0 && h.x == sidelength)
                {
                    // south pole
                    quad = 11;
                    h.x  = 0;
                    h.y  = 0;
                    h.z  = 0;
                }
                else if (h.x == sidelength)
                {
                    quad = quad + 1;
                    if (quad == 11)
                    {
                        quad = 6;
                    }
                    h.x = h.y + sidelength;
                    h.y = 0;
                    h.z = -h.x;
                }
                else if (h.y == -sidelength)
                {
                    quad -= 4;
                    h.y   = 0;
                    h.z   = -h.x;
                }
            }
            di.x = h.x;
            di.y = -h.z;

            g.quad = quad;
            return(quad);
        }
Beispiel #19
0
        static int isea_dddi_ap3odd(ref isea_dgg g, int quad, isea_pt pt, out isea_pt di)
        {
            // This is the number of hexes from apex to base of a triangle
            double sidelength = (Math.Pow(2.0, g.resolution) + 1.0) / 2.0;       // in hexes

            // apex to base is cos(30deg)
            double hexwidth = Math.Cos(Math.PI / 6.0) / sidelength;

            // TODO I think sidelength is always x.5, so
            // (int)sidelength * 2 + 1 might be just as good
            int maxcoord = (int)(sidelength * 2.0 + 0.5);

            isea_pt v = pt;
            hex     h;

            h.z = 0;
            hexbin2(hexwidth, v.x, v.y, out h.x, out h.y);
            h.iso = false;
            hex_iso(ref h);

            int d = h.x - h.z;
            int i = h.x + h.y + h.y;

            // you want to test for max coords for the next quad in the same
            // "row" first to get the case where both are max
            if (quad <= 5)
            {
                if (d == 0 && i == maxcoord)
                {
                    // north pole
                    quad = 0;
                    d    = 0;
                    i    = 0;
                }
                else if (i == maxcoord)
                {
                    // upper right in next quad
                    quad += 1;
                    if (quad == 6)
                    {
                        quad = 1;
                    }
                    i = maxcoord - d;
                    d = 0;
                }
                else if (d == maxcoord)
                {
                    // lower right in quad to lower right
                    quad += 5;
                    d     = 0;
                }
            }
            else if (quad >= 6)
            {
                if (i == 0 && d == maxcoord)
                {
                    // south pole
                    quad = 11;
                    d    = 0;
                    i    = 0;
                }
                else if (d == maxcoord)
                {
                    // lower right in next quad
                    quad += 1;
                    if (quad == 11)
                    {
                        quad = 6;
                    }
                    d = maxcoord - i;
                    i = 0;
                }
                else if (i == maxcoord)
                {
                    // upper right in quad to upper right
                    quad = (quad - 4) % 5;
                    i    = 0;
                }
            }

            di.x = d;
            di.y = i;

            g.quad = quad;
            return(quad);
        }
Beispiel #20
0
        static int isea_tri_plane(int tri, ref isea_pt pt, double radius)
        {
            isea_pt tc; // center of triangle

            if(((tri-1)/5)%2==1) isea_rotate(ref pt, 180.0);

            tc=isea_triangle_xy(tri);
            tc.x*=radius;
            tc.y*=radius;
            pt.x+=tc.x;
            pt.y+=tc.y;

            return tri;
        }
Beispiel #21
0
        // TODO just encode the quad in the d or i coordinate
        // quad is 0-11, which can be four bits.
        // d' = d << 4 + q, d = d' >> 4, q = d' & 0xf

        // convert a q2di to global hex coord
        static int isea_hex(ref isea_dgg g, int tri, isea_pt pt, out isea_pt hex)
        {
            isea_pt v;
            int     quad = isea_ptdi(ref g, tri, pt, out v);

            hex.x = ((int)v.x << 4) + quad;
            hex.y = v.y;

            return(1);

// silence the compiler
#if false
            double d = v.x;
            double i = v.y;

            // Aperture 3 odd resolutions
            if (g.aperture == 3 && g.resolution % 2 != 0)
            {
                int offset = (int)(Math.Pow(3.0, g.resolution - 1) + 0.5);

                d += offset * ((g.quad - 1) % 5);
                i += offset * ((g.quad - 1) % 5);

                if (quad == 0)
                {
                    d = 0;
                    i = offset;
                }
                else if (quad == 11)
                {
                    d = 2 * offset;
                    i = 0;
                }
                else if (quad > 5)
                {
                    d += offset;
                }

                double x = (2 * d - i) / 3;
                double y = (2 * i - d) / 3;

                hex.x = x + offset / 3;
                hex.y = y + 2 * offset / 3;

                return(1);
            }

            // aperture 3 even resolutions and aperture 4
            double sidelength = (int)(Math.Pow(g.aperture, g.resolution / 2.0) + 0.5);
            if (g.quad == 0)
            {
                hex.x = 0;
                hex.y = sidelength;
            }
            else if (g.quad == 11)
            {
                hex.x = sidelength * 2;
                hex.y = 0;
            }
            else
            {
                hex.x = d + sidelength * ((g.quad - 1) % 5);
                if (g.quad > 5)
                {
                    hex.x += sidelength;
                }
                hex.y = i + sidelength * ((g.quad - 1) % 5);
            }

            return(1);
#endif
        }