コード例 #1
0
ファイル: Globe.cpp プロジェクト: kalwalt/ofxVTerrain
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;
}
コード例 #2
0
ファイル: StructArray.cpp プロジェクト: kalwalt/ofxVTerrain
void vtStructureArray::Offset(const DPoint2 &delta)
{
	uint npoints = GetSize();
	if (!npoints)
		return;

	uint i, j;
	DPoint2 temp;
	for (i = 0; i < npoints; i++)
	{
		vtStructure *str = GetAt(i);
		vtBuilding *bld = str->GetBuilding();
		if (bld)
			bld->Offset(delta);
		vtFence *fen = str->GetFence();
		if (fen)
		{
			DLine2 line = fen->GetFencePoints();
			for (j = 0; j < line.GetSize(); j++)
				line.GetAt(j) += delta;
		}
		vtStructInstance *inst = str->GetInstance();
		if (inst)
			inst->Offset(delta);
	}
}
コード例 #3
0
ファイル: Icosa.cpp プロジェクト: kamalsirsa/vtp
void DymaxIcosa::AddFlatTri(DLine2Array &polys, int a, int b, int c, int d)
{
	DLine2 poly;
	poly.Append(m_flatverts[a]);
	poly.Append(m_flatverts[b]);
	poly.Append(m_flatverts[c]);
	if (d != -1)
		poly.Append(m_flatverts[d]);
	polys.push_back(poly);
}
コード例 #4
0
ファイル: Building.cpp プロジェクト: kalwalt/ofxVTerrain
/**
 * Sets the base footprint of the building to be a circle.  A circle
 * is represented by a 20-sided polygonal footprint.
 *
 * \param center The location of the building's center.
 * \param fRad The radius of the building.
 */
void vtBuilding::SetCircle(const DPoint2 &center, float fRad)
{
	DLine2 fp;
	int i;
	for (i = 0; i < 20; i++)
	{
		double angle = i * PI2d / 20;
		DPoint2 vec(cos(angle) * fRad, sin(angle) * fRad);
		fp.Append(center + vec);
	}
	SetFootprint(0, fp);
}
コード例 #5
0
ファイル: UtilityMap.cpp プロジェクト: kamalsirsa/vtp
//
// Make a polyline for this vtLine by using the points from each node.
//
void vtLine::MakePolyline(DLine2 &polyline)
{
	const uint num = m_poles.size();
	polyline.SetSize(num);
	for (uint i = 0; i < num; i++)
		polyline[i] = m_poles[i]->m_p;
}
コード例 #6
0
ファイル: Building.cpp プロジェクト: kalwalt/ofxVTerrain
void vtLevel::SetFootprint(const DLine2 &dl)
{
	// Safety check: Make sure there is at least an outer polygon
	if (m_Foot.size() == 0)
		m_Foot.resize(1);

	int prev = m_Foot[0].GetSize();
	m_Foot[0] = dl;
	int curr = dl.GetSize();
	if (curr != prev)
		RebuildEdges(curr);
}
コード例 #7
0
ファイル: PolyChecker.cpp プロジェクト: kamalsirsa/vtp
bool PolyChecker::IsSimplePolygon(const DLine2 &vertices)
{
	int iSize = vertices.GetSize();
	int i,j;

	for (i = 0; i < iSize - 2; i++)
		for (j = i + 2; j < (i == 0 ? iSize - 1 : iSize); j++)
			if (Intersect(vertices[i], vertices[(i + 1) % iSize],
						  vertices[j], vertices[(j+ 1) % iSize]))
				return false;
	return true;
}
コード例 #8
0
ファイル: StructArray.cpp プロジェクト: kalwalt/ofxVTerrain
void DLine2FromString(const char *data, DLine2 &line)
{
	// Speed/memory optimization: quick check of how many vertices
	//  there are, then preallocate that many
	uint verts = 0;
	for (size_t i = 0; i < strlen(data); i++)
		if (data[i] == ',')
			verts++;
	line.Empty();
	line.SetMaxSize(verts);

	double x, y;
	while (sscanf(data, "%lf,%lf", &x, &y) == 2)
	{
		line.Append(DPoint2(x,y));
		data = strchr(data, ' ');
		if (!data)
			break;
		data++;
	}
}
コード例 #9
0
ファイル: Building.cpp プロジェクト: kalwalt/ofxVTerrain
void vtBuilding::SetRectangle(const DPoint2 &center, float fWidth,
							  float fDepth, float fRotation)
{
	vtLevel *pLev;

	// this function requires at least one level to exist
	if (m_Levels.GetSize() == 0)
	{
		pLev = new vtLevel;
		pLev->m_iStories = 1;
		m_Levels.Append(pLev);
	}
	else
		pLev = m_Levels[0];

	// if rotation is unset, default to none
	if (fRotation == -1.0f)
		fRotation = 0.0f;

	DPoint2 pt(fWidth / 2.0, fDepth / 2.0);
	DPoint2 corner[4];
	corner[0].Set(-pt.x, -pt.y);
	corner[1].Set(pt.x, -pt.y);
	corner[2].Set(pt.x, pt.y);
	corner[3].Set(-pt.x, pt.y);
	corner[0].Rotate(fRotation);
	corner[1].Rotate(fRotation);
	corner[2].Rotate(fRotation);
	corner[3].Rotate(fRotation);

	DLine2 dl;
	dl.Append(center + corner[0]);
	dl.Append(center + corner[1]);
	dl.Append(center + corner[2]);
	dl.Append(center + corner[3]);

	pLev->SetFootprint(dl);
}
コード例 #10
0
ファイル: PolyChecker.cpp プロジェクト: kamalsirsa/vtp
bool PolyChecker::IsClockwisePolygon(const DLine2 &vertices)
{
	DPoint2 p1, p2;
	int iSize = vertices.GetSize();
	// Cannot remember if this works for all Jordan
	double Area = 0;

	for (int i = 0; i < iSize; i++)
	{
		p1 = vertices[i];
		p2 = vertices[(i+1)%iSize];

		Area += (p2.x - p1.x) * (p2.y + p1.y);
	}

	if (Area > 0)
		return true;
	else
		return false;
}
コード例 #11
0
ファイル: HeightField.cpp プロジェクト: kamalsirsa/vtp
/**
 * Create a set of points on the heightfield for a 2D polyline by draping the point onto
 * the surface.
 *
 * \param line	The 2D line to drape, in Earth coordinates.
 * \param fSpacing	The approximate spacing of the surface tessellation, used to
 *		decide how finely to tessellate the line.
 * \param fOffset	An offset to elevate each point in the resulting geometry,
 *		useful for keeping it visibly above the ground.
 * \param bInterp	True to interpolate between the vertices of the input
 *		line. This is generally desirable when the ground is much more finely
 *		spaced than the input line.
 * \param bCurve	True to interpret the vertices of the input line as
 *		control points of a curve.  The created geometry will consist of
 *		a draped line which passes through the control points.
 * \param bTrue		True to use the true elevation of the terrain, ignoring
 *		whatever scale factor is being used to exaggerate elevation for
 *		display.
 * \param output	Received the points.
 * \return The approximate length of the resulting 3D polyline.
 */
float vtHeightField3d::LineOnSurface(const DLine2 &line, float fSpacing, float fOffset,
	bool bInterp, bool bCurve, bool bTrue, FLine3 &output)
{
	uint i, j;
	FPoint3 v1, v2, v;

	float fTotalLength = 0.0f;
	int iVerts = 0;
	uint points = line.GetSize();
	if (bCurve)
	{
		DPoint2 p2, last(1E9,1E9);
		DPoint3 p3;

		int spline_points = 0;
		CubicSpline spline;
		for (i = 0; i < points; i++)
		{
			p2 = line[i];
			if (i > 1 && p2 == last)
				continue;
			p3.Set(p2.x, p2.y, 0);
			spline.AddPoint(p3);
			spline_points++;
			last = p2;
		}
		spline.Generate();

		// Estimate how many steps to subdivide this line into
		const double dLinearLength = line.Length();
		float fLinearLength, dummy;
		m_LocalCS.VectorEarthToLocal(DPoint2(dLinearLength, 0.0), fLinearLength, dummy);
		double full = (double) (spline_points-1);
		int iSteps = (uint) (fLinearLength / fSpacing);
		if (iSteps < 3)
			iSteps = 3;
		double dStep = full / iSteps;

		FPoint3 last_v;
		for (double f = 0; f <= full; f += dStep)
		{
			spline.Interpolate(f, &p3);

			m_LocalCS.EarthToLocal(p3.x, p3.y, v.x, v.z);
			FindAltitudeAtPoint(v, v.y, bTrue);
			v.y += fOffset;
			output.Append(v);
			iVerts++;

			// keep a running total of approximate ground length
			if (f > 0)
				fTotalLength += (v - last_v).Length();
			last_v = v;
		}
	}
	else
	{
		// not curved: straight line in earth coordinates
		FPoint3 last_v;
		for (i = 0; i < points; i++)
		{
			if (bInterp)
			{
				v1 = v2;
				m_LocalCS.EarthToLocal(line[i].x, line[i].y, v2.x, v2.z);
				if (i == 0)
					continue;

				// estimate how many steps to subdivide this segment into
				FPoint3 diff = v2 - v1;
				float fLen = diff.Length();
				uint iSteps = (uint) (fLen / fSpacing);
				if (iSteps < 1) iSteps = 1;

				for (j = (i == 1 ? 0:1); j <= iSteps; j++)
				{
					// simple linear interpolation of the ground coordinate
					v.Set(v1.x + diff.x / iSteps * j, 0.0f, v1.z + diff.z / iSteps * j);
					FindAltitudeAtPoint(v, v.y, bTrue);
					v.y += fOffset;
					output.Append(v);
					iVerts++;

					// keep a running total of approximate ground length
					if (j > 0)
						fTotalLength += (v - last_v).Length();
					last_v = v;
				}
			}
			else
			{
				m_LocalCS.EarthToLocal(line[i], v.x, v.z);
				FindAltitudeAtPoint(v, v.y, bTrue);
				v.y += fOffset;
				output.Append(v);
			}
		}
	}
	return fTotalLength;
}
コード例 #12
0
ファイル: VegLayer.cpp プロジェクト: kamalsirsa/vtp
void vtVegLayer::AddElementsFromLULC(vtLULCFile *pLULC)
{
	LULCSection *section;
	LULCPoly *poly;

	SetVegType(VLT_Density);

	//set projections
	vtProjection proj_new;
	proj_new.SetProjectionSimple(0, -1, EPSG_DATUM_WGS84);
	SetProjection(proj_new);

	// figure out the number of polygons in file
	uint size = 0;
	for (uint sec = 0; sec < pLULC->NumSections(); sec++)
	{
		section = pLULC->GetSection(sec);
		size = size + section->m_iNumPolys;
	}

	// Create density field
	m_field_density = m_pSet->AddField("Density", FT_Float);
	m_pSet->SetNumEntities(size);

	// get each poly from LULC file
	uint i, s, p, count = 0;
	float density=0;
	for (s = 0; s < pLULC->NumSections(); s++)
	{
		section = pLULC->GetSection(s);
		for (p = 0; p < section->m_iNumPolys; p++)
		{
			poly = section->m_pPoly + p;

			bool wild = false;
			switch (poly->Attribute)
			{
				case 42:	// forest
					wild = true;
					density = 1.0f;
					break;
				case 32:
				case 33:
					wild = true;
					density = 0.5;
					break;
				case 22:	// orchards
					wild = false;
					// no crops for now
					break;
				default:
					density = 0.0f;
					break;
			}
			DLine2 dline;
			dline.SetSize(poly->m_iCoords);

			// get Coords of LULCpoly and store as latlon, then save in VPoly
			for (i = 0; i < dline.GetSize(); i++)
				dline.SetAt(i, poly->m_p[i]);

			DPolygon2 dpoly;
			dpoly.push_back(dline);

			GetPS()->SetPolygon(count, dpoly);
			m_pSet->SetValue(count, m_field_density, density);

			count++;
		}
	}
}
コード例 #13
0
ファイル: vtTin.cpp プロジェクト: kamalsirsa/vtp
/**
 * Combine all vertices which are at the same location.  By removing these
 * redundant vertices, the mesh will consume less space in memory and on disk.
 */
void vtTin::MergeSharedVerts(bool progress_callback(int))
{
	uint verts = NumVerts();

	uint i, j;
	int bin;

	DRECT rect = m_EarthExtents;
	double width = rect.Width();

	// make it slightly larger avoid edge condition
	rect.left -= 0.000001;
	width += 0.000002;

	m_bReplace = new int[verts];
	m_vertbin = new Bin[BINS];
	m_tribin = new Bin[BINS];

	// sort the vertices into bins
	for (i = 0; i < verts; i++)
	{
		// flag all vertices initially not to remove
		m_bReplace[i] = -1;

		// find the correct bin, and add the index of this vertex to it
		bin = (int) (BINS * (m_vert[i].x - rect.left) / width);
		m_vertbin[bin].push_back(i);
	}
	uint trisize = m_tri.size();
	for (i = 0; i < trisize; i++)
	{
		// find the correct bin, and add the index of this index to it
		bin = (int) (BINS * (m_vert[m_tri[i]].x - rect.left) / width);
		m_tribin[bin].push_back(i);
	}

	// compare within each bin, and between each adjacent bin,
	// looking for matching vertices to flag for removal
	for (bin = 0; bin < BINS; bin++)
	{
		if (progress_callback != NULL)
			progress_callback(bin * 100 / BINS);

		_CompareBins(bin, bin);
		if (bin < BINS-1)
			_CompareBins(bin, bin+1);
	}
	// now update each triangle index to point to the merge result
	for (bin = 0; bin < BINS; bin++)
	{
		if (progress_callback != NULL)
			progress_callback(bin * 100 / BINS);

		_UpdateIndicesInInBin(bin);
	}

	// now compact the vertex bins into a single array

	// make a copy to copy from
	DLine2 *vertcopy = new DLine2(m_vert);
	float *zcopy = new float[m_z.size()];
	for (i = 0; i < m_z.size(); i++)
		zcopy[i] = m_z[i];

	int inew = 0;	// index into brand new array (actually re-using old)

	for (bin = 0; bin < BINS; bin++)
	{
		if (progress_callback != NULL)
			progress_callback(bin * 100 / BINS);

		uint binverts = m_vertbin[bin].size();
		for (i = 0; i < binverts; i++)
		{
			int v_old = m_vertbin[bin].at(i);
			if (m_bReplace[v_old] != -1)
				continue;

			int v_new = inew;

			// copy old to new
			m_vert[v_new] = vertcopy->GetAt(v_old);
			m_z[v_new] = zcopy[v_old];

			uint bintris = m_tribin[bin].size();
			for (j = 0; j < bintris; j++)
			{
				int trindx = m_tribin[bin].at(j);
				if (m_tri[trindx] == v_old)
					m_tri[trindx] = v_new;
			}
			inew++;
		}
	}

	// our original array containers now hold the compacted result
	int newsize = inew;
	m_vert.SetSize(newsize);
	m_z.resize(newsize);

	// free up all the stuff we allocated
	delete [] m_bReplace;
	delete [] m_vertbin;
	delete [] m_tribin;
	delete vertcopy;
	delete [] zcopy;
}
コード例 #14
0
ファイル: StructArray.cpp プロジェクト: kalwalt/ofxVTerrain
void StructureVisitor::startElement (const char * name, const XMLAttributes &atts)
{
	int i;

	if (_level == 0)
	{
		if (string(name) != (string)"structures-file")
		{
			string message = "Root element name is ";
			message += name;
			message += "; expected structures-file";
			throw xh_io_exception(message, "XML Reader");
		}
		push_state(NULL, "top");
		return;
	}

	if (_level == 1)
	{
		if (string(name) == (string)"coordinates")
		{
			const char *type  = atts.getValue("type");
			const char *value = atts.getValue("value");
			m_pSA->m_proj.SetTextDescription(type, value);
			g_Conv.Setup(m_pSA->m_proj.GetUnits(), DRECT(0,1,1,0));
		}
		else if (string(name) == (string)"structures")
		{
			push_state(NULL, "structures");
		}
		else
		{
			// Unknown element: ignore
			push_state(NULL, "dummy");
		}
		return;
	}

	const char *attval;

	if (_level == 2)
	{
		vtStructure *pStruct = NULL;
		if (string(name) == (string)"structure")
		{
			// Get the name.
			attval = atts.getValue("type");
			if (attval != NULL)
			{
				if (string(attval) == (string)"building")
				{
					vtBuilding *bld = m_pSA->NewBuilding();
					pStruct = bld;
				}
				if (string(attval) == (string)"linear")
				{
					vtFence *fen = m_pSA->NewFence();
					pStruct = fen;
				}
				if (string(attval) == (string)"instance")
				{
					vtStructInstance *inst = m_pSA->NewInstance();
					pStruct = inst;
				}
			}
			push_state(pStruct, "structure");
		}
		else
		{
			// Unknown field, ignore.
			pStruct = NULL;
			push_state(pStruct, "dummy");
		}
		return;
	}

	State &st = state();
	vtStructure *pStruct = st.item;
	if (!pStruct)
		return;
	vtFence *fen = pStruct->GetFence();
	vtBuilding *bld = pStruct->GetBuilding();
	vtStructInstance *inst = pStruct->GetInstance();

	if (_level == 3 && bld != NULL)
	{
		if (string(name) == (string)"height")
		{
			attval = atts.getValue("stories");
			if (attval)
			{
				// height in stories ("floors")
				int stories = atoi(attval);
				if (bld)
					bld->SetStories(stories);
			}
		}
		if (string(name) == (string)"walls")
		{
			attval = atts.getValue("color");
			if (bld && attval)
				st.wall_color = ParseRGB(attval);
		}
		if (string(name) == (string)"shapes")
		{
			push_state(pStruct, "shapes");
			return;
		}
		if (string(name) == (string)"roof")
		{
			// hack to postpone setting building color until now
			bld->SetColor(BLD_BASIC, st.wall_color);

			const char *type = atts.getValue("type");
			if (bld && (string)type == (string)"flat")
				bld->SetRoofType(ROOF_FLAT);
			if (bld && (string)type == (string)"shed")
				bld->SetRoofType(ROOF_SHED);
			if (bld && (string)type == (string)"gable")
				bld->SetRoofType(ROOF_GABLE);
			if (bld && (string)type == (string)"hip")
				bld->SetRoofType(ROOF_HIP);
			attval = atts.getValue("color");
			if (bld && attval)
				bld->SetColor(BLD_ROOF, ParseRGB(attval));
		}
		if (string(name) == (string)"points")
		{
			attval = atts.getValue("num");
		}
		return;
	}
	if (_level == 3 && fen != NULL)
	{
		if (string(name) == (string)"points")
		{
			int points;
			const char *num = atts.getValue("num");
			points = atoi(num);

			DLine2 &fencepts = fen->GetFencePoints();

			DPoint2 loc;
			const char *coords = atts.getValue("coords");
			const char *cp = coords;
			for (i = 0; i < points; i++)
			{
				sscanf(cp, "%lf %lf", &loc.x, &loc.y);
				fencepts.Append(loc);
				cp = strchr(cp, ' ');
				cp++;
				cp = strchr(cp, ' ');
				cp++;
			}
		}
		if (string(name) == (string)"height")
		{
			// absolute height in meters
			const char *abs_str = atts.getValue("abs");
			if (abs_str)
				fen->GetParams().m_fPostHeight = (float)atof(abs_str);
		}
		if (string(name) == (string)"posts")
		{
			// this linear structure has posts
			const char *type = atts.getValue("type");
			if (0 == strcmp(type, "wood"))
				fen->ApplyStyle(FS_WOOD_POSTS_WIRE);
			else if (0 == strcmp(type, "steel"))
				fen->ApplyStyle(FS_CHAINLINK);
			else
				fen->ApplyStyle(FS_METAL_POSTS_WIRE);

			const char *size = atts.getValue("size");
			FPoint3 postsize;
			postsize.y = fen->GetParams().m_fPostHeight;
			sscanf(size, "%f, %f", &postsize.x, &postsize.z);
			fen->GetParams().m_fPostWidth = postsize.x;
			fen->GetParams().m_fPostDepth = postsize.z;

			const char *spacing = atts.getValue("spacing");
			if (spacing)
				fen->GetParams().m_fPostSpacing = (float)atof(spacing);
		}
		if (string(name) == (string)"connect")
		{
			attval = atts.getValue("type");
			// not supported here
		}
		return;
	}
	if (_level == 3 && inst != NULL)
	{
		if (string(name) == (string)"placement")
		{
			const char *loc = atts.getValue("location");
			if (loc)
			{
				DPoint2 p;
				sscanf(loc, "%lf %lf", &p.x, &p.y);
				inst->SetPoint(p);
			}
			const char *rot = atts.getValue("rotation");
			if (rot)
			{
				float fRot;
				sscanf(rot, "%f", &fRot);
				inst->SetRotation(fRot);
			}
		}
		else
			_data = "";
	}
	if (_level == 4 && bld != NULL)
	{
		if (string(name) == (string)"rect")
		{
			DPoint2 loc;
			FPoint2 size2;
			const char *ref_point = atts.getValue("ref_point");
			if (ref_point)
			{
				sscanf(ref_point, "%lf %lf", &loc.x, &loc.y);
				bld->SetRectangle(loc, 10, 10);
			}
			float fRotation = 0.0f;
			const char *rot = atts.getValue("rot");
			if (rot)
			{
				fRotation = (float)atof(rot);
			}
			const char *size = atts.getValue("size");
			if (size)
			{
				sscanf(size, "%f, %f", &size2.x, &size2.y);
				bld->SetRectangle(loc, size2.x, size2.y, fRotation);
			}
		}
		if (string(name) == (string)"circle")
		{
			DPoint2 loc;
			const char *ref_point = atts.getValue("ref_point");
			if (ref_point)
			{
				sscanf(ref_point, "%lf %lf", &loc.x, &loc.y);
				bld->SetCircle(loc, 10);
			}
			const char *radius = atts.getValue("radius");
			if (radius)
			{
				bld->SetCircle(loc, (float)atof(radius));
			}
		}
		if (string(name) == (string)"poly")
		{
			int points;
			const char *num = atts.getValue("num");
			points = atoi(num);

			DLine2 foot;
			DPoint2 loc;
			const char *coords = atts.getValue("coords");
			const char *cp = coords;
			for (i = 0; i < points; i++)
			{
				sscanf(cp, "%lf %lf", &loc.x, &loc.y);
				foot.Append(loc);
				cp = strchr(cp, ' ');
				cp++;
				cp = strchr(cp, ' ');
				cp++;
			}
			bld->SetFootprint(0, foot);
		}
	}
}