Exemple #1
0
double vtIcoGlobe::AddSurfaceLineToMesh(vtGeomFactory *pMF, const DLine2 &line)
{
    DPoint2 g1, g2;
    DPoint3 p1, p2;
    double scale = 1.0002;
    int length = 0;
    DMatrix3 rot3;

    pMF->PrimStart();
    int i, j, size = line.GetSize();

    for (i = 0; i < size-1; i++)
    {
        g1 = line.GetAt(i);
        g2 = line.GetAt(i+1);

        // for each pair of points, determine how many more points are needed
        //  for a smooth arc
        geo_to_xyz(1.0, g1, p1);
        geo_to_xyz(1.0, g2, p2);
        double angle = acos(p1.Dot(p2));
        int segments = (int) (angle * 2000);
        if (segments < 1)
            segments = 1;

        if (segments > 1)
        {
            // calculate the axis of rotation
            DPoint3 cross = p1.Cross(p2);
            cross.Normalize();
            rot3.AxisAngle(cross, angle / segments);
        }

        // curved arc on great-circle path
        for (j = 0; j < segments; j++)
        {
            FPoint3 fp = p1 * 1.0002;
            pMF->AddVertex(fp);
            length++;

            if (j < segments-1)
            {
                rot3.Transform(p1, p2);
                p1 = p2;
            }
        }
    }

    // last vertex
    if (size > 1)
    {
        g2 = line.GetAt(size-1);
        geo_to_xyz(1.0, g2, p2);
        pMF->AddVertex(p2 * scale);
        length++;
    }

    pMF->PrimEnd();
    return 0.0;
}
Exemple #2
0
/**
 * Given a geographic coordinate (lon, lat), find the corresponding
 * face, subface, and UVW coordinates on surface of the icosahedron.
 */
void DymaxIcosa::FindFaceUV(const DPoint2 &p, int &face, int &subface,
							DPoint3 &uvw)
{
	DPoint3 p3;

	geo_to_xyz(p, p3);
	FindFace(p3, face, subface);
	FindUV(p3, face, uvw);
}
Exemple #3
0
double vtIcoGlobe::AddSurfaceLineToMesh(vtGeomFactory *pMF, const DPoint2 &g1, const DPoint2 &g2)
{
    // first determine how many points we should use for a smooth arc
    DPoint3 p1, p2;
    geo_to_xyz(1.0, g1, p1);
    geo_to_xyz(1.0, g2, p2);
    double dot = p1.Dot(p2);
    double angle = acos(dot);
    int points = (int) (angle * 3000);
    if (points < 2)
        points = 2;

    pMF->PrimStart();
    if (points == 2)
    {
        // simple case
        pMF->AddVertex(p1*1.0002);
        pMF->AddVertex(p2*1.0002);
    }
    else
    {
        // calculate the axis of rotation
        DPoint3 cross = p1.Cross(p2);
        cross.Normalize();
        double angle_spacing = angle / (points-1);
        DMatrix4 rot4;
        rot4.AxisAngle(cross, angle_spacing);
        DMatrix3 rot3;
        rot3.SetByMatrix4(rot4);

        // curved arc on great-circle path
        for (int i = 0; i < points; i++)
        {
            FPoint3 fp = p1 * 1.0002;
            pMF->AddVertex(fp);
            rot3.Transform(p1, p2);
            p1 = p2;
        }
    }
    pMF->PrimEnd();
    return angle;
}
Exemple #4
0
/**
 * Given a geographic coordinate (lon, lat), find the corresponding
 * point on the surface of the icosahedron.
 */
void DymaxIcosa::GeoToFacePoint(const DPoint2 &p, int &face, int &subface,
							 DPoint3 &p_out)
{
	DPoint3 p3, uvw;

	geo_to_xyz(p, p3);
	FindFace(p3, face, subface);
	FindUV(p3, face, uvw);

	p_out = m_face[face].base +
		   (m_face[face].vec_a * uvw.x) +
		   (m_face[face].vec_b * uvw.y);
}
Exemple #5
0
void vtIcoGlobe::BuildSphericalPoints(GlobeLayer *glay, float fSize)
{
    vtFeatureSet *feat = glay->m_pSet;
    int i, j, size;
    vtArray<FSphere> spheres;

    size = feat->GetNumEntities();
    spheres.SetSize(size);

    vtFeatureSetPoint2D *pSetP2 = dynamic_cast<vtFeatureSetPoint2D*>(feat);
    if (!pSetP2)
        return;

    DPoint2 p;
    for (i = 0; i < size; i++)
    {
        pSetP2->GetPoint(i, p);

        if (p.x == 0.0 && p.y == 0.0)	// ignore some
            continue;

        FPoint3 loc;
        geo_to_xyz(1.0, p, loc);

        spheres[i].center = loc;
        spheres[i].radius = fSize;
    }

    FPoint3 diff;

    // volume of sphere, 4/3 PI r^3
    // surface area of sphere, 4 PI r^2
    // area of circle of sphere as seen from distance, PI r^2
    int merges;
    do {
        merges = 0;
        // Try merging overlapping points together, so that information
        // is not lost in the overlap.
        // To consider: do we combine the blobs based on their 2d radius,
        // their 2d area, their 3d radius, or their 3d volume?  See
        // Tufte, http://www.edwardtufte.com/
        // Implemented here: preserve 2d area
        for (i = 0; i < size-1; i++)
        {
            for (j = i+1; j < size; j++)
            {
                if (spheres[i].radius == 0.0f || spheres[j].radius == 0.0f)
                    continue;

                diff = spheres[i].center - spheres[j].center;

                // if one sphere contains the center of the other
                if (diff.Length() < spheres[i].radius ||
                        diff.Length() < spheres[j].radius)
                {
                    // combine
                    float area1 = PIf * spheres[i].radius * spheres[i].radius;
                    float area2 = PIf * spheres[j].radius * spheres[j].radius;
                    float combined = (area1 + area2);
                    float newrad = sqrtf( combined / PIf );
                    // larger eats the smaller
                    if (area1 > area2)
                    {
                        spheres[i].radius = newrad;
                        spheres[j].radius = 0.0f;
                    }
                    else
                    {
                        spheres[j].radius = newrad;
                        spheres[i].radius = 0.0f;
                    }
                    merges++;
                    break;
                }
            }
        }
    }
    while (merges != 0);

    // Now create and place the little geometry objects to represent the
    // point data.

#if 0
    // create simple hemisphere mesh
    int res = 6;
    vtMesh *mesh = new vtMesh(osg::PrimitiveSet::TRIANGLE_STRIP, 0, res*res*2);
    FPoint3 scale(1.0f, 1.0f, 1.0f);
    mesh->CreateEllipsoid(scale, res, true);
#else
    // create cylinder mesh instead
    int res = 14;
    int verts = res * 2;
    vtMesh *mesh = new vtMesh(osg::PrimitiveSet::TRIANGLE_STRIP, 0, verts);
    mesh->CreateCylinder(1.0f, 1.0f, res, true, false, false);
#endif

    // use Area to show amount, otherwise height
    bool bArea = true;

    // create and place the geometries
    size = spheres.GetSize();
    for (i = 0; i < size; i++)
    {
        if (spheres[i].radius == 0.0f)
            continue;

        vtGeode *geode = new vtGeode;
        geode->SetMaterials(m_coremats);
        geode->AddMesh(mesh, m_yellow);

        vtMovGeode *mgeom = new vtMovGeode(geode);
        mgeom->setName("GlobeShape");

        mgeom->PointTowards(spheres[i].center);
        mgeom->RotateLocal(FPoint3(1,0,0), -PID2f);
        mgeom->SetTrans(spheres[i].center);
        if (bArea)
        {
            // scale just the radius of the cylinder
            mgeom->Scale3(spheres[i].radius, 0.001f, spheres[i].radius);
        }
        else
        {
            // scale just the height of the cylinder
            double area = PIf * spheres[i].radius * spheres[i].radius;
            mgeom->Scale3(0.002f, (float)area*1000, 0.002f);
        }
        m_SurfaceGroup->addChild(mgeom);
        glay->addChild(mgeom);
    }
}
Exemple #6
0
void geo_to_xyz(double radius, const DPoint2 &geo, FPoint3 &p)
{
    DPoint3 dp;
    geo_to_xyz(radius, geo, dp);
    p = dp;
}
Exemple #7
0
/**
 * Given a geographic coordinate (lon, lat), find the corresponding
 * dymaxion map coordinate, on the classic flattened dymaxion map.
 * The output is unit-edge triangles, which means the whole output
 * extents are x [0, 5.5] and y [0, 2.6].
 */
bool DymaxIcosa::GeoToDymax(const DPoint2 &geo, DPoint2 &dymax)
{
	DPoint3 p3, uvw;
	int face, subface;

	geo_to_xyz(geo, p3);
	FindFace(p3, face, subface);
	FindUV(p3, face, uvw);

	DPoint2 uv(uvw.x, uvw.y);
	//assert(uv.x <= 1 && uv.y <= 1);

	// Not exactly sure why we need to do this - apparently the UV are
	//  assuming a unit-radius, rather than unit-edge icosahedron
	uv /= m_edge_length;

	int a, b, c;
	switch (face)
	{
	case 0:
		a = 17; b = 22; c = 16; break;
	case 1:
		a = 17; b = 16; c = 10; break;
	case 2:
		a = 17; b = 10; c = 11; break;
	case 3:
		a = 17; b = 11; c = 18; break;
	case 4:
		a = 17; b = 23; c = 22; break;
	case 5:
		a = 21; b = 16; c = 22; break;
	case 6:
		a = 16; b = 15; c = 9; break;
	case 7:
		a = 9; b = 10; c = 16; break;
	case 8:
		if (subface == 4 || subface == 5)
			{ a = 10; b = 1; c = 2; }
		else
			{ a = 10; b = 9; c = 1; }
		break;
	case 9:
		a = 2; b = 11; c = 10; break;
	case 10:
		a = 11; b = 3; c = 12; break;
	case 11:
		a = 12; b = 18; c = 11; break;
	case 12:
		a = 18; b = 12; c = 19; break;
	case 13:
		a = 19; b = 24; c = 18; break;
	case 14:
		a = 25; b = 19; c = 20; break;
	case 15:
		if (subface == 0 || subface == 4 || subface == 5)
			{ a = 13; b = 26; c = 20; }
		else
			{ a = 0; b = 9; c = 8; }
		break;
	case 16:
		a = 0; b = 1; c = 9; break;
	case 17:
		a = 4; b = 12; c = 3; break;
	case 18:
		a = 13; b = 19; c = 12; break;
	case 19:
		a = 13; b = 20; c = 19; break;
	default:
		return false;
	}
	DPoint2 base = m_flatverts[a];
	DPoint2 vec1 = m_flatverts[b] - base;
	DPoint2 vec2 = m_flatverts[c] - base;

	dymax = base + (vec1 * uv.x) + (vec2 * uv.y);
	return true;
}