Esempio n. 1
0
void vtIcoGlobe::CreateCoreMaterials()
{
    m_coremats = new vtMaterialArray;
    m_red = m_coremats->AddRGBMaterial1(RGBf(1.0f, 0.0f, 0.0f),	// red
                                        false, false, true);
    m_yellow = m_coremats->AddRGBMaterial1(RGBf(1.0f, 1.0f, 0.0f),	// yellow
                                           false, false, false);
    m_white = m_coremats->AddRGBMaterial1(RGBf(0.2f, 0.2f, 0.2f),
                                          true, true, true, 1);
    m_coremats->at(m_white)->SetTransparent(true, true);
}
Esempio n. 2
0
void vtRoute::_CreateMaterials()
{
	m_pRouteMats = new vtMaterialArray;

	// add wire material (0)
	m_mi_wire = m_pRouteMats->AddRGBMaterial(RGBf(0.0f, 0.0f, 0.0f), // diffuse
//		RGBf(0.5f, 0.5f, 0.5f),	// ambient grey
		RGBf(1.5f, 1.5f, 1.5f),	// ambient bright white
		false, true, false,		// culling, lighting, wireframe
		1.0f);					// alpha
}
Esempio n. 3
0
void Style::CreateDefaultStyle(hStyle h) {
    bool isDefaultStyle = true;
    const Default *d;
    for(d = &(Defaults[0]); d->h.v; d++) {
        if(d->h.v == h.v) break;
    }
    if(!d->h.v) {
        // Not a default style; so just create it the same as our default
        // active group entity style.
        d = &(Defaults[0]);
        isDefaultStyle = false;
    }

    Style ns;
    ZERO(&ns);
    ns.color        = CnfThawColor(d->color, CnfColor(d->cnfPrefix));
    ns.width        = CnfThawFloat((float)(d->width), CnfWidth(d->cnfPrefix));
    ns.widthAs      = UNITS_AS_PIXELS;
    ns.textHeight   = DEFAULT_TEXT_HEIGHT;
    ns.textHeightAs = UNITS_AS_PIXELS;
    ns.textOrigin   = 0;
    ns.textAngle    = 0;
    ns.visible      = true;
    ns.exportable   = true;
    ns.filled       = false;
    ns.fillColor    = RGBf(0.3, 0.3, 0.3);
    ns.h            = h;
    if(isDefaultStyle) {
        ns.name.strcpy(CnfPrefixToName(d->cnfPrefix));
    } else {
        ns.name.strcpy("new-custom-style");
    }

    SK.style.Add(&ns);
}
Esempio n. 4
0
ElasticPolyline::ElasticPolyline()
{
	m_Materials = new vtMaterialArray;
	m_Materials->AddRGBMaterial1(RGBf(1, 0.5, 0), true, true);			// orange solid
	m_Materials->AddRGBMaterial1(RGBf(1, 1, 0.5), false, false, true);	// light yellow wireframe

	// Create a marker post to use for each corner of the polyline
	int matidx = 0;		// orange
	float fRadius = 0.1f;
	m_Marker = CreateCylinderGeom(m_Materials, matidx, VT_Normals, 1.0f,
		fRadius, 10, true, false, false, 1);

	m_Container = new vtGroup;
	m_pTerr = NULL;

	// Defaults
	m_fPostHeight = 1.0f;
	m_fLineHeight = 1.0f;
}
Esempio n. 5
0
void Style::FillDefaultStyle(Style *s, const Default *d, bool factory) {
    if(d == NULL) d = &Defaults[0];
    s->color         = (factory) ? d->color : CnfThawColor(d->color, CnfColor(d->cnfPrefix));
    s->width         = (factory) ? d->width : CnfThawFloat((float)(d->width), CnfWidth(d->cnfPrefix));
    s->widthAs       = UnitsAs::PIXELS;
    s->textHeight    = (factory) ? DEFAULT_TEXT_HEIGHT
                                 : CnfThawFloat(DEFAULT_TEXT_HEIGHT, CnfTextHeight(d->cnfPrefix));
    s->textHeightAs  = UnitsAs::PIXELS;
    s->textOrigin    = TextOrigin::NONE;
    s->textAngle     = 0;
    s->visible       = true;
    s->exportable    = true;
    s->filled        = false;
    s->fillColor     = RGBf(0.3, 0.3, 0.3);
    s->stippleType   = (d->h.v == Style::HIDDEN_EDGE) ? StipplePattern::DASH
                                                      : StipplePattern::CONTINUOUS;
    s->stippleScale  = 15.0;
    s->zIndex        = d->zIndex;
}
Esempio n. 6
0
void Style::LoadFactoryDefaults(void) {
    const Default *d;
    for(d = &(Defaults[0]); d->h.v; d++) {
        Style *s = Get(d->h);

        s->color        = d->color;
        s->width        = d->width;
        s->widthAs      = UNITS_AS_PIXELS;
        s->textHeight   = DEFAULT_TEXT_HEIGHT;
        s->textHeightAs = UNITS_AS_PIXELS;
        s->textOrigin   = 0;
        s->textAngle    = 0;
        s->visible      = true;
        s->exportable   = true;
        s->filled       = false;
        s->fillColor    = RGBf(0.3, 0.3, 0.3);
        s->name.strcpy(CnfPrefixToName(d->cnfPrefix));
    }
    SS.backgroundColor = RGBi(0, 0, 0);
    if(SS.bgImage.fromFile) MemFree(SS.bgImage.fromFile);
    SS.bgImage.fromFile = NULL;
}
Esempio n. 7
0
/**
 * Get the emissive color of this material.
 */
RGBf vtMaterial::GetEmission() const
{
	osg::Vec4 col = m_pMaterial->getEmission(FAB);
	return RGBf(col[0], col[1], col[2]);
}
Esempio n. 8
0
//
// Test code
//
void EnviroFrame::DoTestCode()
{
	SetMode(MM_SLOPE);

#if 0
	// Shadow tests
	const int ReceivesShadowTraversalMask = 0x1;
	const int CastsShadowTraversalMask = 0x2;

	osg::ref_ptr<osgShadow::ShadowedScene> shadowedScene = new osgShadow::ShadowedScene;

	shadowedScene->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask);
	shadowedScene->setCastsShadowTraversalMask(CastsShadowTraversalMask);

#if 0
	osg::ref_ptr<osgShadow::ShadowMap> sm = new osgShadow::ShadowMap;
	shadowedScene->setShadowTechnique(sm.get());
	int mapres = 1024;
	sm->setTextureSize(osg::Vec2s(mapres,mapres));
#else
	osg::ref_ptr<osgShadow::ShadowTexture> sm = new osgShadow::ShadowTexture;
	shadowedScene->setShadowTechnique(sm.get());
#endif

	osg::Group* cessna1 = (osg::Group*) osgDB::readNodeFile("cessna.osg");
	if (!cessna1)
		return;
	cessna1->setNodeMask(CastsShadowTraversalMask);
	cessna1->getChild(0)->setNodeMask(CastsShadowTraversalMask);

	osg::Group* cessna2 = (osg::Group*) osgDB::readNodeFile("cessna.osg");
	if (!cessna2)
		return;
	int flags_off = ~(CastsShadowTraversalMask | ReceivesShadowTraversalMask);
	cessna2->setNodeMask(flags_off);
	cessna2->getChild(0)->setNodeMask(flags_off);

	osg::MatrixTransform* positioned = new osg::MatrixTransform;
	positioned->setDataVariance(osg::Object::STATIC);
	positioned->setMatrix(osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,1.0f,0.0f)
		*osg::Matrix::translate(40,40,0));
	positioned->addChild(cessna1);

//osg::ref_ptr<osg::Group> shadowedScene = new osg::Group;
	shadowedScene->addChild(positioned);
	shadowedScene->addChild(cessna2);

	//	osg::ref_ptr<osg::Group> container = new osg::Group;
	//	container->addChild(positioned);
	//    container->addChild(cessna2);

	vtGroup *vtg = GetCurrentTerrain()->GetTerrainGroup();
	vtg->GetOsgGroup()->addChild(shadowedScene.get());
	//	vtg->GetOsgGroup()->addChild(container.get());

	vtLogGraph(shadowedScene.get());
#endif
#if 0
	if (pTerr && g_App.m_bSelectedStruct)
	{
		vtStructureArray3d *sa = pTerr->GetStructureLayer();
		int i = 0;
		while (!sa->GetAt(i)->IsSelected())
			i++;
		vtBuilding3d *bld = sa->GetBuilding(i);
		// (Do something to the building as a test)
		sa->ConstructStructure(bld);
	}
#endif
#if 0
	{
		// Read points from a text file, create OBJ file with geometry at that locations
		FILE *fp = fopen("test.txt", "r");
		if (!fp) return;

		char buf[80];
		float depth, x, y;

		// Add the geometry and materials to the shape
		vtGeode *pGeode = new vtGeode;
		vtMaterialArray *pMats = new vtMaterialArray;
		pMats->AddRGBMaterial(RGBf(1.0f, 1.0f, 1.0f), false, false, false);
		pGeode->SetMaterials(pMats);

		vtMesh *mesh = new vtMesh(osg::PrimitiveSet::TRIANGLES, VT_Normals | VT_Colors, 4000);

		int line = 0;
		fgets(buf, 80, fp);	// skip first
		while (fgets(buf, 80, fp) != NULL)
		{
			sscanf(buf, "%f\t%f\t%f", &depth, &x, &y);
			int idx = mesh->NumVertices();
			for (int i = 0; i < 20; i++)
			{
				double angle = (double)i / 20.0 * PI2d;
				FPoint3 vec;
				vec.x = x/2 * cos(angle);
				vec.y = 0.0f;
				vec.z = y/2 * sin(angle);

				// normal
				FPoint3 norm = vec;
				norm.Normalize();

				// color
				RGBAf col(1.0f, 1.0f, 1.0f, 1.0f);
				if (x > y)
				{
					float frac = (x-y)/1.5f;	// typical: 0 - 1.2
					col.g -= frac;
					col.b -= frac;
				}
				else if (y > x)
				{
					float frac = (y-x)/1.5f;	// typical: 0 - 1.2
					col.r -= frac;
					col.g -= frac;
				}

				int add = mesh->AddVertexN(vec.x, /*650*/-depth, vec.z,
					norm.x, norm.y, norm.z);
				mesh->SetVtxColor(add, col);
			}
			if (line != 0)
			{
				for (int i = 0; i < 20; i++)
				{
					int next = (i+1)%20;
					mesh->AddTri(idx-20 + i, idx + i,    idx-20 + next);
					mesh->AddTri(idx    + i, idx + next, idx-20 + next);
				}
			}
			line++;
		}
		pGeode->AddMesh(mesh, 0);
		WriteGeomToOBJ(pGeode, "bore.obj");

		vtTransform *model = new vtTransform;
		model->addChild(pGeode);
		DPoint3 pos;
		g_App.m_pTerrainPicker->GetCurrentEarthPos(pos);
		GetCurrentTerrain()->AddNode(model);
		GetCurrentTerrain()->PlantModelAtPoint(model, DPoint2(pos.x, pos.y));
	}
#endif
}
Esempio n. 9
0
void Constraint::DrawOrGetDistance(Vector *labelPos) {
    if(!SS.GW.showConstraints) return;
    Group *g = SK.GetGroup(group);
    // If the group is hidden, then the constraints are hidden and not
    // able to be selected.
    if(!(g->visible)) return;
    // And likewise if the group is not the active group; except for comments
    // with an assigned style.
    if(g->h.v != SS.GW.activeGroup.v && !(type == COMMENT && disp.style.v)) {
        return;
    }
    if(disp.style.v) {
        Style *s = Style::Get(disp.style);
        if(!s->visible) return;
    }

    // Unit vectors that describe our current view of the scene. One pixel
    // long, not one actual unit.
    Vector gr = SS.GW.projRight.ScaledBy(1/SS.GW.scale);
    Vector gu = SS.GW.projUp.ScaledBy(1/SS.GW.scale);
    Vector gn = (gr.Cross(gu)).WithMagnitude(1/SS.GW.scale);

    switch(type) {
        case PT_PT_DISTANCE: {
            Vector ap = SK.GetEntity(ptA)->PointGetNum();
            Vector bp = SK.GetEntity(ptB)->PointGetNum();

            if(workplane.v != Entity::FREE_IN_3D.v) {
                DoProjectedPoint(&ap);
                DoProjectedPoint(&bp);
            }

            Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(disp.offset);

            DoLineWithArrows(ref, ap, bp, false);
            DoLabel(ref, labelPos, gr, gu);
            break;
        }

        case PROJ_PT_DISTANCE: {
            Vector ap = SK.GetEntity(ptA)->PointGetNum(),
                   bp = SK.GetEntity(ptB)->PointGetNum(),
                   dp = (bp.Minus(ap)),
                   pp = SK.GetEntity(entityA)->VectorGetNum();

            Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(disp.offset);

            pp = pp.WithMagnitude(1);
            double d = dp.Dot(pp);
            Vector bpp = ap.Plus(pp.ScaledBy(d));
            StippledLine(ap, bpp);
            StippledLine(bp, bpp);

            DoLineWithArrows(ref, ap, bpp, false);
            DoLabel(ref, labelPos, gr, gu);
            break;
        }

        case PT_FACE_DISTANCE:
        case PT_PLANE_DISTANCE: {
            Vector pt = SK.GetEntity(ptA)->PointGetNum();
            Entity *enta = SK.GetEntity(entityA);
            Vector n, p;
            if(type == PT_PLANE_DISTANCE) {
                n = enta->Normal()->NormalN();
                p = enta->WorkplaneGetOffset();
            } else {
                n = enta->FaceGetNormalNum();
                p = enta->FaceGetPointNum();
            }

            double d = (p.Minus(pt)).Dot(n);
            Vector closest = pt.Plus(n.WithMagnitude(d));

            Vector ref = ((closest.Plus(pt)).ScaledBy(0.5)).Plus(disp.offset);

            if(!pt.Equals(closest)) {
                DoLineWithArrows(ref, pt, closest, true);
            }

            DoLabel(ref, labelPos, gr, gu);
            break;
        }

        case PT_LINE_DISTANCE: {
            Vector pt = SK.GetEntity(ptA)->PointGetNum();
            Entity *line = SK.GetEntity(entityA);
            Vector lA = SK.GetEntity(line->point[0])->PointGetNum();
            Vector lB = SK.GetEntity(line->point[1])->PointGetNum();
            Vector dl = lB.Minus(lA);

            if(workplane.v != Entity::FREE_IN_3D.v) {
                lA = lA.ProjectInto(workplane);
                lB = lB.ProjectInto(workplane);
                DoProjectedPoint(&pt);
            }

            // Find the closest point on the line
            Vector closest = pt.ClosestPointOnLine(lA, dl);

            Vector ref = ((closest.Plus(pt)).ScaledBy(0.5)).Plus(disp.offset);
            DoLabel(ref, labelPos, gr, gu);

            if(!pt.Equals(closest)) {
                DoLineWithArrows(ref, pt, closest, true);
            }

            if(workplane.v != Entity::FREE_IN_3D.v) {
                // Draw the projection marker from the closest point on the
                // projected line to the projected point on the real line.
                Vector lAB = (lA.Minus(lB));
                double t = (lA.Minus(closest)).DivPivoting(lAB);

                Vector lA = SK.GetEntity(line->point[0])->PointGetNum();
                Vector lB = SK.GetEntity(line->point[1])->PointGetNum();

                Vector c2 = (lA.ScaledBy(1-t)).Plus(lB.ScaledBy(t));
                DoProjectedPoint(&c2);
            }
            break;
        }

        case DIAMETER: {
            Entity *circle = SK.GetEntity(entityA);
            Vector center = SK.GetEntity(circle->point[0])->PointGetNum();
            Quaternion q = SK.GetEntity(circle->normal)->NormalGetNum();
            Vector n = q.RotationN().WithMagnitude(1);
            double r = circle->CircleGetRadiusNum();

            Vector ref = center.Plus(disp.offset);
            // Force the label into the same plane as the circle.
            ref = ref.Minus(n.ScaledBy(n.Dot(ref) - n.Dot(center)));

            Vector mark = ref.Minus(center);
            mark = mark.WithMagnitude(mark.Magnitude()-r);
            DoLineTrimmedAgainstBox(ref, ref, ref.Minus(mark));

            Vector topLeft;
            DoLabel(ref, &topLeft, gr, gu);
            if(labelPos) *labelPos = topLeft;

            // Show this as diameter or radius?
            if(!other) {
                // Draw the diameter symbol
                Vector dc = topLeft;
                dc = dc.Plus(gu.WithMagnitude(5/SS.GW.scale));
                dc = dc.Plus(gr.WithMagnitude(9/SS.GW.scale));
                double dr = 5/SS.GW.scale;
                double theta, dtheta = (2*PI)/12;
                for(theta = 0; theta < 2*PI-0.01; theta += dtheta) {
                    LineDrawOrGetDistance(
                        dc.Plus(gu.WithMagnitude(cos(theta)*dr)).Plus(
                                gr.WithMagnitude(sin(theta)*dr)),
                        dc.Plus(gu.WithMagnitude(cos(theta+dtheta)*dr)).Plus(
                                gr.WithMagnitude(sin(theta+dtheta)*dr)));
                }
                theta = 25*(PI/180);
                dr *= 1.7;
                dtheta = PI;
                LineDrawOrGetDistance(
                    dc.Plus(gu.WithMagnitude(cos(theta)*dr)).Plus(
                            gr.WithMagnitude(sin(theta)*dr)),
                    dc.Plus(gu.WithMagnitude(cos(theta+dtheta)*dr)).Plus(
                            gr.WithMagnitude(sin(theta+dtheta)*dr)));
            }
            break;
        }

        case POINTS_COINCIDENT: {
            if(!dogd.drawing) {
                for(int i = 0; i < 2; i++) {
                    Vector p = SK.GetEntity(i == 0 ? ptA : ptB)-> PointGetNum();
                    Point2d pp = SS.GW.ProjectPoint(p);
                    // The point is selected within a radius of 7, from the
                    // same center; so if the point is visible, then this
                    // constraint cannot be selected. But that's okay.
                    dogd.dmin = min(dogd.dmin, pp.DistanceTo(dogd.mp) - 3);
                    dogd.refp = p;
                }
                break;
            }

            if(dogd.drawing) {
                // Let's adjust the color of this constraint to have the same
                // rough luma as the point color, so that the constraint does not
                // stand out in an ugly way.
                RgbaColor cd = Style::Color(Style::DATUM),
                         cc = Style::Color(Style::CONSTRAINT);
                // convert from 8-bit color to a vector
                Vector vd = Vector::From(cd.redF(), cd.greenF(), cd.blueF()),
                       vc = Vector::From(cc.redF(), cc.greenF(), cc.blueF());
                // and scale the constraint color to have the same magnitude as
                // the datum color, maybe a bit dimmer
                vc = vc.WithMagnitude(vd.Magnitude()*0.9);
                // and set the color to that.
                ssglColorRGB(RGBf(vc.x, vc.y, vc.z));

                for(int a = 0; a < 2; a++) {
                    Vector r = SS.GW.projRight.ScaledBy((a+1)/SS.GW.scale);
                    Vector d = SS.GW.projUp.ScaledBy((2-a)/SS.GW.scale);
                    for(int i = 0; i < 2; i++) {
                        Vector p = SK.GetEntity(i == 0 ? ptA : ptB)-> PointGetNum();
                        glBegin(GL_QUADS);
                            ssglVertex3v(p.Plus (r).Plus (d));
                            ssglVertex3v(p.Plus (r).Minus(d));
                            ssglVertex3v(p.Minus(r).Minus(d));
                            ssglVertex3v(p.Minus(r).Plus (d));
                        glEnd();
                    }

                }
            }
            break;
        }

        case PT_ON_CIRCLE:
        case PT_ON_LINE:
        case PT_ON_FACE:
        case PT_IN_PLANE: {
            double s = 8/SS.GW.scale;
            Vector p = SK.GetEntity(ptA)->PointGetNum();
            Vector r, d;
            if(type == PT_ON_FACE) {
                Vector n = SK.GetEntity(entityA)->FaceGetNormalNum();
                r = n.Normal(0);
                d = n.Normal(1);
            } else if(type == PT_IN_PLANE) {
                EntityBase *n = SK.GetEntity(entityA)->Normal();
                r = n->NormalU();
                d = n->NormalV();
            } else {
                r = gr;
                d = gu;
                s *= (6.0/8); // draw these a little smaller
            }
            r = r.WithMagnitude(s); d = d.WithMagnitude(s);
            LineDrawOrGetDistance(p.Plus (r).Plus (d), p.Plus (r).Minus(d));
            LineDrawOrGetDistance(p.Plus (r).Minus(d), p.Minus(r).Minus(d));
            LineDrawOrGetDistance(p.Minus(r).Minus(d), p.Minus(r).Plus (d));
            LineDrawOrGetDistance(p.Minus(r).Plus (d), p.Plus (r).Plus (d));
            break;
        }

        case WHERE_DRAGGED: {
            Vector p = SK.GetEntity(ptA)->PointGetNum(),
                   u = p.Plus(gu.WithMagnitude(8/SS.GW.scale)).Plus(
                              gr.WithMagnitude(8/SS.GW.scale)),
                   uu = u.Minus(gu.WithMagnitude(5/SS.GW.scale)),
                   ur = u.Minus(gr.WithMagnitude(5/SS.GW.scale));
            // Draw four little crop marks, uniformly spaced (by ninety
            // degree rotations) around the point.
            int i;
            for(i = 0; i < 4; i++) {
                LineDrawOrGetDistance(u, uu);
                LineDrawOrGetDistance(u, ur);
                u = u.RotatedAbout(p, gn, PI/2);
                ur = ur.RotatedAbout(p, gn, PI/2);
                uu = uu.RotatedAbout(p, gn, PI/2);
            }
            break;
        }

        case SAME_ORIENTATION: {
            for(int i = 0; i < 2; i++) {
                Entity *e = SK.GetEntity(i == 0 ? entityA : entityB);
                Quaternion q = e->NormalGetNum();
                Vector n = q.RotationN().WithMagnitude(25/SS.GW.scale);
                Vector u = q.RotationU().WithMagnitude(6/SS.GW.scale);
                Vector p = SK.GetEntity(e->point[0])->PointGetNum();
                p = p.Plus(n.WithMagnitude(10/SS.GW.scale));

                LineDrawOrGetDistance(p.Plus(u), p.Minus(u).Plus(n));
                LineDrawOrGetDistance(p.Minus(u), p.Plus(u).Plus(n));
            }
            break;
        }

        case EQUAL_ANGLE: {
            Vector ref;
            Entity *a = SK.GetEntity(entityA);
            Entity *b = SK.GetEntity(entityB);
            Entity *c = SK.GetEntity(entityC);
            Entity *d = SK.GetEntity(entityD);

            Vector a0 = a->VectorGetRefPoint();
            Vector b0 = b->VectorGetRefPoint();
            Vector c0 = c->VectorGetRefPoint();
            Vector d0 = d->VectorGetRefPoint();
            Vector da = a->VectorGetNum();
            Vector db = b->VectorGetNum();
            Vector dc = c->VectorGetNum();
            Vector dd = d->VectorGetNum();

            if(other) da = da.ScaledBy(-1);

            DoArcForAngle(a0, da, b0, db,
                da.WithMagnitude(40/SS.GW.scale), &ref);
            DoArcForAngle(c0, dc, d0, dd,
                dc.WithMagnitude(40/SS.GW.scale), &ref);

            break;
        }

        case ANGLE: {
            Entity *a = SK.GetEntity(entityA);
            Entity *b = SK.GetEntity(entityB);

            Vector a0 = a->VectorGetRefPoint();
            Vector b0 = b->VectorGetRefPoint();
            Vector da = a->VectorGetNum();
            Vector db = b->VectorGetNum();
            if(other) da = da.ScaledBy(-1);

            Vector ref;
            DoArcForAngle(a0, da, b0, db, disp.offset, &ref);
            DoLabel(ref, labelPos, gr, gu);
            break;
        }

        case PERPENDICULAR: {
            Vector u = Vector::From(0, 0, 0), v = Vector::From(0, 0, 0);
            Vector rn, ru;
            if(workplane.v == Entity::FREE_IN_3D.v) {
                rn = gn;
                ru = gu;
            } else {
                EntityBase *normal = SK.GetEntity(workplane)->Normal();
                rn = normal->NormalN();
                ru = normal->NormalV(); // ru meaning r_up, not u/v
            }

            for(int i = 0; i < 2; i++) {
                Entity *e = SK.GetEntity(i == 0 ? entityA : entityB);

                if(i == 0) {
                    // Calculate orientation of perpendicular sign only
                    // once, so that it's the same both times it's drawn
                    u = e->VectorGetNum();
                    u = u.WithMagnitude(16/SS.GW.scale);
                    v = (rn.Cross(u)).WithMagnitude(16/SS.GW.scale);
                    // a bit of bias to stop it from flickering between the
                    // two possibilities
                    if(fabs(u.Dot(ru)) < fabs(v.Dot(ru)) + LENGTH_EPS) {
                        SWAP(Vector, u, v);
                    }
                    if(u.Dot(ru) < 0) u = u.ScaledBy(-1);
                }

                Vector p = e->VectorGetRefPoint();
                Vector s = p.Plus(u).Plus(v);
                LineDrawOrGetDistance(s, s.Plus(v));

                Vector m = s.Plus(v.ScaledBy(0.5));
                LineDrawOrGetDistance(m, m.Plus(u));
            }
            break;
        }

        case CURVE_CURVE_TANGENT:
        case CUBIC_LINE_TANGENT:
        case ARC_LINE_TANGENT: {
            Vector textAt, u, v;

            if(type == ARC_LINE_TANGENT) {
                Entity *arc = SK.GetEntity(entityA);
                Entity *norm = SK.GetEntity(arc->normal);
                Vector c = SK.GetEntity(arc->point[0])->PointGetNum();
                Vector p =
                    SK.GetEntity(arc->point[other ? 2 : 1])->PointGetNum();
                Vector r = p.Minus(c);
                textAt = p.Plus(r.WithMagnitude(14/SS.GW.scale));
                u = norm->NormalU();
                v = norm->NormalV();
            } else if(type == CUBIC_LINE_TANGENT) {
                Vector n;
                if(workplane.v == Entity::FREE_IN_3D.v) {
                    u = gr;
                    v = gu;
                    n = gn;
                } else {
                    EntityBase *wn = SK.GetEntity(workplane)->Normal();
                    u = wn->NormalU();
                    v = wn->NormalV();
                    n = wn->NormalN();
                }

                Entity *cubic = SK.GetEntity(entityA);
                Vector p = other ? cubic->CubicGetFinishNum() :
                                   cubic->CubicGetStartNum();
                Vector dir = SK.GetEntity(entityB)->VectorGetNum();
                Vector out = n.Cross(dir);
                textAt = p.Plus(out.WithMagnitude(14/SS.GW.scale));
            } else {
                Vector n, dir;
                EntityBase *wn = SK.GetEntity(workplane)->Normal();
                u = wn->NormalU();
                v = wn->NormalV();
                n = wn->NormalN();
                EntityBase *eA = SK.GetEntity(entityA);
                // Big pain; we have to get a vector tangent to the curve
                // at the shared point, which could be from either a cubic
                // or an arc.
                if(other) {
                    textAt = eA->EndpointFinish();
                    if(eA->type == Entity::CUBIC) {
                        dir = eA->CubicGetFinishTangentNum();
                    } else {
                        dir = SK.GetEntity(eA->point[0])->PointGetNum().Minus(
                              SK.GetEntity(eA->point[2])->PointGetNum());
                        dir = n.Cross(dir);
                    }
                } else {
                    textAt = eA->EndpointStart();
                    if(eA->type == Entity::CUBIC) {
                        dir = eA->CubicGetStartTangentNum();
                    } else {
                        dir = SK.GetEntity(eA->point[0])->PointGetNum().Minus(
                              SK.GetEntity(eA->point[1])->PointGetNum());
                        dir = n.Cross(dir);
                    }
                }
                dir = n.Cross(dir);
                textAt = textAt.Plus(dir.WithMagnitude(14/SS.GW.scale));
            }

            if(dogd.drawing) {
                ssglWriteTextRefCenter("T", DEFAULT_TEXT_HEIGHT,
                    textAt, u, v, LineCallback, this);
            } else {
                dogd.refp = textAt;
                Point2d ref = SS.GW.ProjectPoint(dogd.refp);
                dogd.dmin = min(dogd.dmin, ref.DistanceTo(dogd.mp)-10);
            }
            break;
        }

        case PARALLEL: {
            for(int i = 0; i < 2; i++) {
                Entity *e = SK.GetEntity(i == 0 ? entityA : entityB);
                Vector n = e->VectorGetNum();
                n = n.WithMagnitude(25/SS.GW.scale);
                Vector u = (gn.Cross(n)).WithMagnitude(4/SS.GW.scale);
                Vector p = e->VectorGetRefPoint();

                LineDrawOrGetDistance(p.Plus(u), p.Plus(u).Plus(n));
                LineDrawOrGetDistance(p.Minus(u), p.Minus(u).Plus(n));
            }
            break;
        }

        case EQUAL_RADIUS: {
            for(int i = 0; i < 2; i++) {
                DoEqualRadiusTicks(i == 0 ? entityA : entityB);
            }
            break;
        }

        case EQUAL_LINE_ARC_LEN: {
            Entity *line = SK.GetEntity(entityA);
            DoEqualLenTicks(
                SK.GetEntity(line->point[0])->PointGetNum(),
                SK.GetEntity(line->point[1])->PointGetNum(),
                gn);

            DoEqualRadiusTicks(entityB);
            break;
        }

        case LENGTH_RATIO:
        case EQUAL_LENGTH_LINES: {
            Vector a, b = Vector::From(0, 0, 0);
            for(int i = 0; i < 2; i++) {
                Entity *e = SK.GetEntity(i == 0 ? entityA : entityB);
                a = SK.GetEntity(e->point[0])->PointGetNum();
                b = SK.GetEntity(e->point[1])->PointGetNum();

                if(workplane.v != Entity::FREE_IN_3D.v) {
                    DoProjectedPoint(&a);
                    DoProjectedPoint(&b);
                }

                DoEqualLenTicks(a, b, gn);
            }
            if(type == LENGTH_RATIO) {
                Vector ref = ((a.Plus(b)).ScaledBy(0.5)).Plus(disp.offset);
                DoLabel(ref, labelPos, gr, gu);
            }
            break;
        }

        case EQ_LEN_PT_LINE_D: {
            Entity *forLen = SK.GetEntity(entityA);
            Vector a = SK.GetEntity(forLen->point[0])->PointGetNum(),
                   b = SK.GetEntity(forLen->point[1])->PointGetNum();
            if(workplane.v != Entity::FREE_IN_3D.v) {
                DoProjectedPoint(&a);
                DoProjectedPoint(&b);
            }
            DoEqualLenTicks(a, b, gn);

            Entity *ln = SK.GetEntity(entityB);
            Vector la = SK.GetEntity(ln->point[0])->PointGetNum(),
                   lb = SK.GetEntity(ln->point[1])->PointGetNum();
            Vector pt = SK.GetEntity(ptA)->PointGetNum();
            if(workplane.v != Entity::FREE_IN_3D.v) {
                DoProjectedPoint(&pt);
                la = la.ProjectInto(workplane);
                lb = lb.ProjectInto(workplane);
            }

            Vector closest = pt.ClosestPointOnLine(la, lb.Minus(la));
            LineDrawOrGetDistance(pt, closest);
            DoEqualLenTicks(pt, closest, gn);
            break;
        }

        case EQ_PT_LN_DISTANCES: {
            for(int i = 0; i < 2; i++) {
                Entity *ln = SK.GetEntity(i == 0 ? entityA : entityB);
                Vector la = SK.GetEntity(ln->point[0])->PointGetNum(),
                       lb = SK.GetEntity(ln->point[1])->PointGetNum();
                Entity *pte = SK.GetEntity(i == 0 ? ptA : ptB);
                Vector pt = pte->PointGetNum();

                if(workplane.v != Entity::FREE_IN_3D.v) {
                    DoProjectedPoint(&pt);
                    la = la.ProjectInto(workplane);
                    lb = lb.ProjectInto(workplane);
                }

                Vector closest = pt.ClosestPointOnLine(la, lb.Minus(la));

                LineDrawOrGetDistance(pt, closest);
                DoEqualLenTicks(pt, closest, gn);
            }
            break;
        }

        {
        case SYMMETRIC:
            Vector n;
            n = SK.GetEntity(entityA)->Normal()->NormalN(); goto s;
        case SYMMETRIC_HORIZ:
            n = SK.GetEntity(workplane)->Normal()->NormalU(); goto s;
        case SYMMETRIC_VERT:
            n = SK.GetEntity(workplane)->Normal()->NormalV(); goto s;
        case SYMMETRIC_LINE: {
            Entity *ln = SK.GetEntity(entityA);
            Vector la = SK.GetEntity(ln->point[0])->PointGetNum(),
                   lb = SK.GetEntity(ln->point[1])->PointGetNum();
            la = la.ProjectInto(workplane);
            lb = lb.ProjectInto(workplane);
            n = lb.Minus(la);
            Vector nw = SK.GetEntity(workplane)->Normal()->NormalN();
            n = n.RotatedAbout(nw, PI/2);
            goto s;
        }
s:
            Vector a = SK.GetEntity(ptA)->PointGetNum();
            Vector b = SK.GetEntity(ptB)->PointGetNum();

            for(int i = 0; i < 2; i++) {
                Vector tail = (i == 0) ? a : b;
                Vector d = (i == 0) ? b : a;
                d = d.Minus(tail);
                // Project the direction in which the arrow is drawn normal
                // to the symmetry plane; for projected symmetry constraints,
                // they might not be in the same direction, even when the
                // constraint is fully solved.
                d = n.ScaledBy(d.Dot(n));
                d = d.WithMagnitude(20/SS.GW.scale);
                Vector tip = tail.Plus(d);

                LineDrawOrGetDistance(tail, tip);
                d = d.WithMagnitude(9/SS.GW.scale);
                LineDrawOrGetDistance(tip, tip.Minus(d.RotatedAbout(gn,  0.6)));
                LineDrawOrGetDistance(tip, tip.Minus(d.RotatedAbout(gn, -0.6)));
            }
            break;
        }

        case AT_MIDPOINT:
        case HORIZONTAL:
        case VERTICAL:
            if(entityA.v) {
                Vector r, u, n;
                if(workplane.v == Entity::FREE_IN_3D.v) {
                    r = gr; u = gu; n = gn;
                } else {
                    r = SK.GetEntity(workplane)->Normal()->NormalU();
                    u = SK.GetEntity(workplane)->Normal()->NormalV();
                    n = r.Cross(u);
                }
                // For "at midpoint", this branch is always taken.
                Entity *e = SK.GetEntity(entityA);
                Vector a = SK.GetEntity(e->point[0])->PointGetNum();
                Vector b = SK.GetEntity(e->point[1])->PointGetNum();
                Vector m = (a.ScaledBy(0.5)).Plus(b.ScaledBy(0.5));
                Vector offset = (a.Minus(b)).Cross(n);
                offset = offset.WithMagnitude(13/SS.GW.scale);
                // Draw midpoint constraint on other side of line, so that
                // a line can be midpoint and horizontal at same time.
                if(type == AT_MIDPOINT) offset = offset.ScaledBy(-1);

                if(dogd.drawing) {
                    const char *s = (type == HORIZONTAL)  ? "H" : (
                                    (type == VERTICAL)    ? "V" : (
                                    (type == AT_MIDPOINT) ? "M" : NULL));

                    ssglWriteTextRefCenter(s, DEFAULT_TEXT_HEIGHT,
                        m.Plus(offset), r, u, LineCallback, this);
                } else {
                    dogd.refp = m.Plus(offset);
                    Point2d ref = SS.GW.ProjectPoint(dogd.refp);
                    dogd.dmin = min(dogd.dmin, ref.DistanceTo(dogd.mp)-10);
                }
            } else {
                Vector a = SK.GetEntity(ptA)->PointGetNum();
                Vector b = SK.GetEntity(ptB)->PointGetNum();

                Entity *w = SK.GetEntity(workplane);
                Vector cu = w->Normal()->NormalU();
                Vector cv = w->Normal()->NormalV();
                Vector cn = w->Normal()->NormalN();

                int i;
                for(i = 0; i < 2; i++) {
                    Vector o = (i == 0) ? a : b;
                    Vector oo = (i == 0) ? a.Minus(b) : b.Minus(a);
                    Vector d = (type == HORIZONTAL) ? cu : cv;
                    if(oo.Dot(d) < 0) d = d.ScaledBy(-1);

                    Vector dp = cn.Cross(d);
                    d = d.WithMagnitude(14/SS.GW.scale);
                    Vector c = o.Minus(d);
                    LineDrawOrGetDistance(o, c);
                    d = d.WithMagnitude(3/SS.GW.scale);
                    dp = dp.WithMagnitude(2/SS.GW.scale);
                    if(dogd.drawing) {
                        glBegin(GL_QUADS);
                            ssglVertex3v((c.Plus(d)).Plus(dp));
                            ssglVertex3v((c.Minus(d)).Plus(dp));
                            ssglVertex3v((c.Minus(d)).Minus(dp));
                            ssglVertex3v((c.Plus(d)).Minus(dp));
                        glEnd();
                    } else {
                        Point2d ref = SS.GW.ProjectPoint(c);
                        dogd.dmin = min(dogd.dmin, ref.DistanceTo(dogd.mp)-6);
                    }
                }
            }
            break;

        case COMMENT: {
            if(dogd.drawing && disp.style.v) {
                ssglLineWidth(Style::Width(disp.style));
                ssglColorRGB(Style::Color(disp.style));
            }
            Vector u, v;
            if(workplane.v == Entity::FREE_IN_3D.v) {
                u = gr;
                v = gu;
            } else {
                EntityBase *norm = SK.GetEntity(workplane)->Normal();
                u = norm->NormalU();
                v = norm->NormalV();
            }
            DoLabel(disp.offset, labelPos, u, v);
            break;
        }

        default: oops();
    }
}
Esempio n. 10
0
bool TextWindow::EditControlDoneForConfiguration(const char *s) {
    switch(edit.meaning) {
        case EDIT_LIGHT_INTENSITY:
            SS.lightIntensity[edit.i] = min(1, max(0, atof(s)));
            InvalidateGraphics();
            break;

        case EDIT_LIGHT_DIRECTION: {
            double x, y, z;
            if(sscanf(s, "%lf, %lf, %lf", &x, &y, &z)==3) {
                SS.lightDir[edit.i] = Vector::From(x, y, z);
            } else {
                Error("Bad format: specify coordinates as x, y, z");
            }
            InvalidateGraphics();
            break;
        }
        case EDIT_COLOR: {
            Vector rgb;
            if(sscanf(s, "%lf, %lf, %lf", &rgb.x, &rgb.y, &rgb.z)==3) {
                rgb = rgb.ClampWithin(0, 1);
                SS.modelColor[edit.i] = RGBf(rgb.x, rgb.y, rgb.z);
            } else {
                Error("Bad format: specify color as r, g, b");
            }
            break;
        }
        case EDIT_CHORD_TOLERANCE: {
            SS.chordTol = min(10, max(0.1, atof(s)));
            SS.GenerateAll(0, INT_MAX);
            break;
        }
//RT New stuff
        case EDIT_RENDERDETAIL: {
			SS.renderDetailWhenSaving =   atof(s);
			if (SS.renderDetailWhenSaving)			SS.GW.scaleWin =SS.renderDetailWhenSaving;
			SS.GenerateAll(0, INT_MAX);
            break;
        }
//RT End stuff
		case EDIT_MAX_SEGMENTS: {
            SS.maxSegments = min(1000, max(7, atoi(s)));
            SS.GenerateAll(0, INT_MAX);
            break;
        }
        case EDIT_CAMERA_TANGENT: {
            SS.cameraTangent = (min(2, max(0, atof(s))))/1000.0;
            if(!SS.usePerspectiveProj) {
                Message("The perspective factor will have no effect until you "
                        "enable View -> Use Perspective Projection.");
            }
            InvalidateGraphics();
            break;
        }
        case EDIT_GRID_SPACING: {
            SS.gridSpacing = (float)min(1e4, max(1e-3, SS.StringToMm(s)));
            InvalidateGraphics();
            break;
        }
        case EDIT_DIGITS_AFTER_DECIMAL: {
            int v = atoi(s);
            if(v < 0 || v > 8) {
                Error("Specify between 0 and 8 digits after the decimal.");
            } else {
                SS.SetUnitDigitsAfterDecimal(v);
            }
            InvalidateGraphics();
            break;
        }
        case EDIT_EXPORT_SCALE: {
            Expr *e = Expr::From(s, true);
            if(e) {
                double ev = e->Eval();
                if(fabs(ev) < 0.001 || isnan(ev)) {
                    Error("Export scale must not be zero!");
                } else {
                    SS.exportScale = (float)ev;
                }
            }
            break;
        }
        case EDIT_EXPORT_OFFSET: {
            Expr *e = Expr::From(s, true);
            if(e) {
                double ev = SS.ExprToMm(e);
                if(isnan(ev) || ev < 0) {
                    Error("Cutter radius offset must not be negative!");
                } else {
                    SS.exportOffset = (float)ev;
                }
            }
            break;
        }
        case EDIT_CANVAS_SIZE: {
            Expr *e = Expr::From(s, true);
            if(!e) {
                break;
            }
            float d = (float)SS.ExprToMm(e);
            switch(edit.i) {
                case  0: SS.exportMargin.left   = d;    break;
                case  1: SS.exportMargin.right  = d;    break;
                case  2: SS.exportMargin.bottom = d;    break;
                case  3: SS.exportMargin.top    = d;    break;

                case 10: SS.exportCanvas.width  = d;    break;
                case 11: SS.exportCanvas.height = d;    break;
                case 12: SS.exportCanvas.dx     = d;    break;
                case 13: SS.exportCanvas.dy     = d;    break;
            }
            break;
        }
        case EDIT_G_CODE_DEPTH: {
            Expr *e = Expr::From(s, true);
            if(e) SS.gCode.depth = (float)SS.ExprToMm(e);
            break;
        }
        case EDIT_G_CODE_PASSES: {
            Expr *e = Expr::From(s, true);
            if(e) SS.gCode.passes = (int)(e->Eval());
            SS.gCode.passes = max(1, min(1000, SS.gCode.passes));
            break;
        }
        case EDIT_G_CODE_FEED: {
            Expr *e = Expr::From(s, true);
            if(e) SS.gCode.feed = (float)SS.ExprToMm(e);
            break;
        }
        case EDIT_G_CODE_PLUNGE_FEED: {
            Expr *e = Expr::From(s, true);
            if(e) SS.gCode.plungeFeed = (float)SS.ExprToMm(e);
            break;
        }

        default: return false;
    }
    return true;
}
Esempio n. 11
0
vtMaterialArray *vtIcoGlobe::CreateMaterialsFromFiles(const vtString &strImagePrefix)
{
    vtMaterialArray *mats = new vtMaterialArray;

#if 0
    if (m_style == INDEPENDENT_GEODESIC)
    {
        int mat = 0;
        for (int pair = 0; pair < 10; pair++)
        {
            for (int j = 0; j < m_freq; j++)
                for (int i = 0; i < m_freq; i++)
                {
                    // TEMP for testing: pretty colors
                    float r = (pair+1) * (1.0f / 10);
                    float g = (j+1) * (1.0f / m_freq);
                    float b = (i+1) * (1.0f / m_freq);
                    m_globe_mat[mat++] = mats->AddRGBMaterial1(RGBf(r, g, b),
                                         true, true);
                }
        }
        return;
    }
#endif
    vtString base;
    vtString fname;
    vtString fullpath;

    bool bCulling = true;
    bool bLighting = false;
    int pair, index;
    for (pair = 0; pair < 10; pair++)
    {
        if (strImagePrefix == "")
        {
            m_globe_mat[pair] = m_white;
            continue;
        }
        int f1 = icosa_face_pairs[pair][0];
        int f2 = icosa_face_pairs[pair][1];

        base = "WholeEarth/";
        base += strImagePrefix;
        base += "_";

        fname.Format("%s%02d%02d.jpg", (const char *)base, f1+1, f2+1);
        VTLOG("\t texture: %s\n", (const char *)fname);

        fullpath = FindFileOnPaths(vtGetDataPath(), (const char *)fname);
        if (fullpath == "")
        {
            // try again with png
            fname.Format("%s%02d%02d.png", (const char *)base, f1+1, f2+1);
            VTLOG("\t texture: %s\n", (const char *)fname);
            fullpath = FindFileOnPaths(vtGetDataPath(), (const char *)fname);
        }
        if (fullpath == "")
        {
            VTLOG("\t\tnot found on data paths.\n");
            index = -1;
        }
        else
        {
            ImagePtr img = osgDB::readImageFile((const char *)fullpath);
            if (img.valid())
            {
                index = mats->AddTextureMaterial(img,
                                                 bCulling, bLighting,
                                                 GetDepth(img) == 32, false,	// transp, additive
                                                 0.1f, 1.0f, 1.0f, 0.0f,		// ambient, diffuse, alpha, emmisive
                                                 false, true, false);		// texgen, clamp, mipmap
            }
            else
                index = -1;
        }
        if (index == -1)
        {
            VTLOG("\t\ttexture load failed, using red material.\n");
            m_globe_mat[pair] = m_red;
        }
        else
            m_globe_mat[pair] = index;
    }
    return mats;
}
Esempio n. 12
0
bool TextWindow::EditControlDoneForStyles(const char *str) {
    Style *s;
    switch(edit.meaning) {
        case EDIT_STYLE_TEXT_HEIGHT:
        case EDIT_STYLE_WIDTH: {
            SS.UndoRemember();
            s = Style::Get(edit.style);

            double v;
            int units = (edit.meaning == EDIT_STYLE_TEXT_HEIGHT) ?
                            s->textHeightAs : s->widthAs;
            if(units == Style::UNITS_AS_MM) {
                v = SS.StringToMm(str);
            } else {
                v = atof(str);
            }
            v = max(0, v);
            if(edit.meaning == EDIT_STYLE_TEXT_HEIGHT) {
                s->textHeight = v;
            } else {
                s->width = v;
            }
            break;
        }
        case EDIT_STYLE_TEXT_ANGLE:
            SS.UndoRemember();
            s = Style::Get(edit.style);
            s->textAngle = WRAP_SYMMETRIC(atof(str), 360);
            break;

        case EDIT_BACKGROUND_COLOR:
        case EDIT_STYLE_FILL_COLOR:
        case EDIT_STYLE_COLOR: {
            Vector rgb;
            if(sscanf(str, "%lf, %lf, %lf", &rgb.x, &rgb.y, &rgb.z)==3) {
                rgb = rgb.ClampWithin(0, 1);
                if(edit.meaning == EDIT_STYLE_COLOR) {
                    SS.UndoRemember();
                    s = Style::Get(edit.style);
                    s->color = RGBf(rgb.x, rgb.y, rgb.z);
                } else if(edit.meaning == EDIT_STYLE_FILL_COLOR) {
                    SS.UndoRemember();
                    s = Style::Get(edit.style);
                    s->fillColor = RGBf(rgb.x, rgb.y, rgb.z);
                } else {
                    SS.backgroundColor = RGBf(rgb.x, rgb.y, rgb.z);
                }
            } else {
                Error("Bad format: specify color as r, g, b");
            }
            break;
        }
        case EDIT_STYLE_NAME:
            if(!StringAllPrintable(str) || !*str) {
                Error("Invalid characters. Allowed are: A-Z a-z 0-9 _ -");
            } else {
                SS.UndoRemember();
                s = Style::Get(edit.style);
                s->name.strcpy(str);
            }
            break;

        case EDIT_BACKGROUND_IMG_SCALE: {
            Expr *e = Expr::From(str, true);
            if(e) {
                double ev = e->Eval();
                if(ev < 0.001 || isnan(ev)) {
                    Error("Scale must not be zero or negative!");
                } else {
                    SS.bgImage.scale = ev / SS.MmPerUnit();
                }
            }
            break;
        }
        default: return false;
    }
    return true;
}
Esempio n. 13
0
void vtIcoGlobe::CreateUnfoldableDymax()
{
    int i;
    for (i = 0; i < 22; i++)
    {
        m_mface[i].xform = new vtTransform;
        m_mface[i].surfgroup = new vtGroup;
        m_mface[i].surfgroup->SetEnabled(false);
        m_mface[i].geode = new vtGeode;
        m_mface[i].xform->addChild(m_mface[i].geode);
        m_mface[i].xform->addChild(m_mface[i].surfgroup);

        vtString str;
        str.Format("IcoFace %d", i);
        m_mface[i].xform->setName(str);

        int face = dymax_subfaces[i].face;
        int subfaces = dymax_subfaces[i].subfaces;

        bool which;
        int mat = GetMaterialForFace(face, which);

        add_face2(m_mesh[i], face, i, subfaces, which);

        m_mface[i].geode->SetMaterials(m_earthmats);
        m_mface[i].geode->AddMesh(m_mesh[i], m_globe_mat[mat]);
    }
    m_top->addChild(m_mface[0].xform);

    m_mface[0].local_origin.Set(0,0,0);
    for (i = 1; i < 22; i++)
        FindLocalOrigin(i);
    for (i = 1; i < 22; i++)
        SetMeshConnect(i);

    // Determine necessary rotation to orient flat map toward viewer.
    FQuat qface;
    DPoint3 v0 = m_verts[icosa_face_v[0][0]];
    DPoint3 v1 = m_verts[icosa_face_v[0][1]];
    DPoint3 v2 = m_verts[icosa_face_v[0][2]];

    // Create a rotation to turn the globe so that a specific edge
    //  is pointed down -X for proper map orientation
    DPoint3 edge = v2 - v0;
    edge.Normalize();

    // compose face norm and face quaternion
    DPoint3 fnorm = (v0 + v1 + v2).Normalize();
    qface.SetFromVectors(edge, fnorm);

    // desired vector points down -X
    FQuat qdesired;
    qdesired.SetFromVectors(FPoint3(-1,0,0),FPoint3(0,0,1));

    // determine rotational difference
    m_diff = qface.Inverse() * qdesired;

#if 0
    // scaffolding mesh for debugging
    vtMesh *sm = new vtMesh(GL_LINES, VT_Colors, 12);
    sm->AddVertex(v0*1.0001f);
    sm->AddVertex(v1*1.0001f);
    sm->AddVertex(v2*1.0001f);
    sm->AddVertex(v0*1.0001f+fnorm);
    sm->SetVtxColor(0, RGBf(1,0,0));
    sm->SetVtxColor(1, RGBf(0,1,0));
    sm->SetVtxColor(2, RGBf(0,0,1));
    sm->SetVtxColor(3, RGBf(1,1,0));
    sm->AddLine(0,1);
    sm->AddLine(0,2);
    sm->AddLine(0,3);
    m_geom[0]->AddMesh(sm, m_red);
    sm->Release();
#endif

    // Show axis of rotation (north and south poles)
    vtMaterialArray *pMats = new vtMaterialArray;
    int green = pMats->AddRGBMaterial1(RGBf(0,1,0), false, false);
    m_pAxisGeom = new vtGeode;
    m_pAxisGeom->setName("AxisGeom");
    m_pAxisGeom->SetMaterials(pMats);
    m_pAxisGeom->SetEnabled(false);

    vtMesh *pMesh = new vtMesh(osg::PrimitiveSet::LINES, 0, 6);
    pMesh->AddVertex(FPoint3(0,2,0));
    pMesh->AddVertex(FPoint3(0,-2,0));
    pMesh->AddLine(0,1);
    m_pAxisGeom->AddMesh(pMesh, green);
    m_top->addChild(m_pAxisGeom);

#if 0
    axis = WireAxis(RGBf(1,1,1), 1.1f);
    m_top->addChild(axis);
#endif
}
Esempio n. 14
0
//-----------------------------------------------------------------------------
// The edit control is visible, and the user just pressed enter.
//-----------------------------------------------------------------------------
void TextWindow::EditControlDone(const char *s) {
    edit.showAgain = false;

    switch(edit.meaning) {
        case EDIT_TIMES_REPEATED: {
            Expr *e = Expr::From(s, true);
            if(e) {
                SS.UndoRemember();

                double ev = e->Eval();
                if((int)ev < 1) {
                    Error("Can't repeat fewer than 1 time.");
                    break;
                }
                if((int)ev > 999) {
                    Error("Can't repeat more than 999 times.");
                    break;
                }

                Group *g = SK.GetGroup(edit.group);
                g->valA = ev;

                if(g->type == Group::ROTATE) {
                    int i, c = 0;
                    for(i = 0; i < SK.constraint.n; i++) {
                        if(SK.constraint.elem[i].group.v == g->h.v) c++;
                    }
                    // If the group does not contain any constraints, then
                    // set the numerical guess to space the copies uniformly
                    // over one rotation. Don't touch the guess if we're
                    // already constrained, because that would break
                    // convergence.
                    if(c == 0) {
                        double copies = (g->skipFirst) ? (ev + 1) : ev;
                        SK.GetParam(g->h.param(3))->val = PI/(2*copies);
                    }
                }

                SS.MarkGroupDirty(g->h);
                SS.later.generateAll = true;
            }
            break;
        }
        case EDIT_GROUP_NAME: {
            if(!StringAllPrintable(s) || !*s) {
                Error("Invalid characters. Allowed are: A-Z a-z 0-9 _ -");
            } else {
                SS.UndoRemember();

                Group *g = SK.GetGroup(edit.group);
                g->name.strcpy(s);
            }
            break;
        }
        case EDIT_GROUP_SCALE: {
            Expr *e = Expr::From(s, true);
            if(e) {
                double ev = e->Eval();
                if(fabs(ev) < 1e-6) {
                    Error("Scale cannot be zero.");
                } else {
                    Group *g = SK.GetGroup(edit.group);
                    g->scale = ev;
                    SS.MarkGroupDirty(g->h);
                    SS.later.generateAll = true;
                }
            }
            break;
        }
        case EDIT_GROUP_COLOR: {
            Vector rgb;
            if(sscanf(s, "%lf, %lf, %lf", &rgb.x, &rgb.y, &rgb.z)==3) {
                rgb = rgb.ClampWithin(0, 1);

                Group *g = SK.group.FindByIdNoOops(SS.TW.shown.group);
                if(!g) break;
                g->color = RGBf(rgb.x, rgb.y, rgb.z);

                SS.MarkGroupDirty(g->h);
                SS.later.generateAll = true;
                SS.GW.ClearSuper();
            } else {
                Error("Bad format: specify color as r, g, b");
            }
            break;
        }
        case EDIT_TTF_TEXT: {
            SS.UndoRemember();
            Request *r = SK.request.FindByIdNoOops(edit.request);
            if(r) {
                r->str.strcpy(s);
                SS.MarkGroupDirty(r->group);
                SS.later.generateAll = true;
            }
            break;
        }
        case EDIT_STEP_DIM_FINISH: {
            Expr *e = Expr::From(s, true);
            if(!e) {
                break;
            }
            if(shown.dimIsDistance) {
                shown.dimFinish = SS.ExprToMm(e);
            } else {
                shown.dimFinish = e->Eval();
            }
            break;
        }
        case EDIT_STEP_DIM_STEPS:
            shown.dimSteps = min(300, max(1, atoi(s)));
            break;

        case EDIT_TANGENT_ARC_RADIUS: {
            Expr *e = Expr::From(s, true);
            if(!e) break;
            if(e->Eval() < LENGTH_EPS) {
                Error("Radius cannot be zero or negative.");
                break;
            }
            SS.tangentArcRadius = SS.ExprToMm(e);
            break;
        }

        default: {
            int cnt = 0;
            if(EditControlDoneForStyles(s))         cnt++;
            if(EditControlDoneForConfiguration(s))  cnt++;
            if(EditControlDoneForPaste(s))          cnt++;
            if(EditControlDoneForView(s))           cnt++;
            if(cnt > 1) {
                // The identifiers were somehow assigned not uniquely?
                oops();
            }
            break;
        }
    }
    InvalidateGraphics();
    SS.later.showTW = true;

    if(!edit.showAgain) {
        HideEditControl();
        edit.meaning = EDIT_NOTHING;
    }
}
Esempio n. 15
0
/**
 * Get the ambient color of this material.
 */
RGBf vtMaterial::GetAmbient() const
{
	osg::Vec4 col = m_pMaterial->getAmbient(FAB);
	return RGBf(col[0], col[1], col[2]);
}
Esempio n. 16
0
/**
 * Get the specular color of this material.
 */
RGBf vtMaterial::GetSpecular() const
{
	osg::Vec4 col = m_pMaterial->getSpecular(FAB);
	return RGBf(col[0], col[1], col[2]);
}
Esempio n. 17
0
//-----------------------------------------------------------------------------
// Implementation of a cosmetic line style, which determines the color and
// other appearance of a line or curve on-screen and in exported files. Some
// styles are predefined, and others can be created by the user.
//
// Copyright 2008-2013 Jonathan Westhues.
//-----------------------------------------------------------------------------
#include "solvespace.h"
#include <png.h>

const Style::Default Style::Defaults[] = {
    { { ACTIVE_GRP },   "ActiveGrp",    RGBf(1.0, 1.0, 1.0), 1.5, },
    { { CONSTRUCTION }, "Construction", RGBf(0.1, 0.7, 0.1), 1.5, },
    { { INACTIVE_GRP }, "InactiveGrp",  RGBf(0.5, 0.3, 0.0), 1.5, },
    { { DATUM },        "Datum",        RGBf(0.0, 0.8, 0.0), 1.5, },
    { { SOLID_EDGE },   "SolidEdge",    RGBf(0.8, 0.8, 0.8), 1.0, },
    { { CONSTRAINT },   "Constraint",   RGBf(1.0, 0.1, 1.0), 1.0, },
    { { SELECTED },     "Selected",     RGBf(1.0, 0.0, 0.0), 1.5, },
    { { HOVERED },      "Hovered",      RGBf(1.0, 1.0, 0.0), 1.5, },
    { { CONTOUR_FILL }, "ContourFill",  RGBf(0.0, 0.1, 0.1), 1.0, },
    { { NORMALS },      "Normals",      RGBf(0.0, 0.4, 0.4), 1.0, },
    { { ANALYZE },      "Analyze",      RGBf(0.0, 1.0, 1.0), 1.0, },
    { { DRAW_ERROR },   "DrawError",    RGBf(1.0, 0.0, 0.0), 8.0, },
    { { DIM_SOLID },    "DimSolid",     RGBf(0.1, 0.1, 0.1), 1.0, },
    { { 0 },            NULL,           NULL_COLOR,          0.0 }
};

char *Style::CnfColor(const char *prefix) {
    static char name[100];
    sprintf(name, "Style_%s_Color", prefix);
    return name;
Esempio n. 18
0
void vtRoadMap3d::_CreateMaterials(bool do_texture)
{
	m_pMats = new vtMaterialArray;

	// road textures
	if (do_texture)
	{
		// TODO: put these literals in a config file somewhere, if needed.
		m_mi_roadside =	_CreateMaterial("roadside_32.png", true);
		m_mi_pavement =	_CreateMaterial("pavement_256.jpg", false);
		m_mi_roads =	_CreateMaterial("roadset_2k.jpg", false);
		m_mi_4wd =		_CreateMaterial("road_4wd2.png", true);
		m_mi_trail =	_CreateMaterial("trail2.png", true);
		m_mi_gravel =	_CreateMaterial("gravel1.png", true);

		m_vt[VTI_MARGIN].m_idx = m_mi_roads;
		m_vt[VTI_MARGIN].m_rect.SetRect(960.0f/ROAD_REZ, 1, 992.0f/ROAD_REZ, 0);

		m_vt[VTI_SIDEWALK].m_idx = m_mi_roads;
		m_vt[VTI_SIDEWALK].m_rect.SetRect(512.0f/ROAD_REZ, 1, 640.0f/ROAD_REZ, 0);

		m_vt[VTI_1LANE].m_idx = m_mi_roads;
		m_vt[VTI_1LANE].m_rect.SetRect(451.0f/ROAD_REZ, 1, 511.0f/ROAD_REZ, 0);

		m_vt[VTI_2LANE1WAY].m_idx = m_mi_roads;
		m_vt[VTI_2LANE1WAY].m_rect.SetRect(4.0f/ROAD_REZ, 1, 124.0f/ROAD_REZ, 0);

		m_vt[VTI_2LANE2WAY].m_idx = m_mi_roads;
		m_vt[VTI_2LANE2WAY].m_rect.SetRect(640.0f/ROAD_REZ, 1, 768.0f/ROAD_REZ, 0);

		m_vt[VTI_3LANE1WAY].m_idx = m_mi_roads;
		m_vt[VTI_3LANE1WAY].m_rect.SetRect(2.0f/ROAD_REZ, 1, 190.0f/ROAD_REZ, 0);

		m_vt[VTI_3LANE2WAY].m_idx = m_mi_roads;
		m_vt[VTI_3LANE2WAY].m_rect.SetRect(768.0f/ROAD_REZ, 1, .0f/ROAD_REZ, 0);

		m_vt[VTI_4LANE1WAY].m_idx = m_mi_roads;
		m_vt[VTI_4LANE1WAY].m_rect.SetRect(0.0f/ROAD_REZ, 1, 256.0f/ROAD_REZ, 0);

		m_vt[VTI_4LANE2WAY].m_idx = m_mi_roads;
		m_vt[VTI_4LANE2WAY].m_rect.SetRect(256.0f/ROAD_REZ, 1, 512.0f/ROAD_REZ, 0);

		m_vt[VTI_RAIL].m_idx = m_mi_roads;
		m_vt[VTI_RAIL].m_rect.SetRect(992.0f/ROAD_REZ, 1, 1248.0f/ROAD_REZ, 0);

		m_vt[VTI_STONE].m_idx = m_mi_roads;
		m_vt[VTI_STONE].m_rect.SetRect(1248.0f/ROAD_REZ, 1, 1440.0f/ROAD_REZ, 0);

		m_vt[VTI_4WD].m_idx = m_mi_4wd;
		m_vt[VTI_4WD].m_rect.SetRect(0, 0, 1, 1);

		m_vt[VTI_TRAIL].m_idx = m_mi_trail;
		m_vt[VTI_TRAIL].m_rect.SetRect(0, 0, 1, 1);

		m_vt[VTI_GRAVEL].m_idx = m_mi_gravel;
		m_vt[VTI_GRAVEL].m_rect.SetRect(0, 0, 1, 1);

		m_vt[VTI_PAVEMENT].m_idx = m_mi_pavement;
		m_vt[VTI_PAVEMENT].m_rect.SetRect(0, 0, 1, 1);
	}
	else
	{
		m_mi_roadside = m_pMats->AddRGBMaterial(RGBf(0.8f, 0.6f, 0.4f), true, false);	// 0 brown roadside
		m_mi_roads = m_pMats->AddRGBMaterial(RGBf(0.0f, 1.0f, 0.0f), true, false);	// 1 green
		m_mi_4wd = m_pMats->AddRGBMaterial(RGBf(0.5f, 0.5f, 0.5f), true, false);	// 2 grey
		m_mi_trail = m_pMats->AddRGBMaterial(RGBf(1.0f, 0.3f, 1.0f), true, false);	// 3 light purple
	}
	m_mi_red = m_pMats->AddRGBMaterial(RGBf(1.0f, 0.0f, 0.0f),
		true, true, false, 0.4f);	// red-translucent
}
Esempio n. 19
0
void vtFence3d::ShowBounds(bool bShow)
{
	if (m_pHighlightMesh)
	{
		// remove previous
		m_pFenceGeom->RemoveMesh(m_pHighlightMesh);
		m_pHighlightMesh = NULL;
	}
	if (bShow)
	{
		uint i, npoints = m_pFencePts.GetSize();

		// Create border around the feature, also some lines as handles for
		//  the control points.
		// Must be tall enough to be visible above all the posts and profile.
		float height = max(m_Params.m_fPostHeight, m_Params.m_fConnectTop);
		float width = m_Params.m_fConnectWidth;
		if (m_Params.m_iConnectType == 3)
		{
			for (i = 0; i < m_Profile.GetSize(); i++)
			{
				float x = fabs(m_Profile[i].x), y = m_Profile[i].y;
				if (y > height) height = y;
				if (x > width) width = x;
			}
		}
		height += 1.0f;
		width += 1.0f;

		// border around the feature
		m_pHighlightMesh = new vtMesh(osg::PrimitiveSet::LINE_STRIP, 0, npoints*2);
		FPoint3 sideways, up(0,1,0);
		for (i = 0; i < npoints; i++)
		{
			// determine normal
			if (i == 0)
				sideways = SidewaysVector(m_Posts3d[i], m_Posts3d[i+1]);
			else if (i > 0 && i < npoints-1)
			{
				AngleSideVector(m_Posts3d[i-1], m_Posts3d[i], m_Posts3d[i+1], sideways);
				sideways = -sideways;	// We want a vector pointing left, not right
			}
			else if (i == npoints-1)
				sideways = SidewaysVector(m_Posts3d[i-1], m_Posts3d[i]);

			sideways.SetLength(width);

			m_pHighlightMesh->AddVertex(m_Posts3d[i] - sideways + up);
			m_pHighlightMesh->AddVertex(m_Posts3d[i] + sideways + up);
		}

		std::vector<unsigned short> idx;
		for (i = 0; i < npoints; i++) idx.push_back(i*2);
		for (i = 0; i < npoints; i++) idx.push_back((npoints*2)-1 - i*2);
		idx.push_back(0);
		m_pHighlightMesh->AddStrip(idx.size(), &idx.front());

		for (i = 0; i < npoints; i++)
		{
			float extra_height = 0.0f;
			if (m_Params.m_bConstantTop)
				extra_height = m_fMaxGroundY - m_Posts3d[i].y;

			int v0 = m_pHighlightMesh->AddVertex(m_Posts3d[i]);
			int v1 = m_pHighlightMesh->AddVertex(m_Posts3d[i] + FPoint3(0,height+extra_height,0));
			m_pHighlightMesh->AddLine(v0, v1);
		}

		// Use yellow highlight material
		int highlight_matidx = GetMatIndex("Highlight", RGBf(1,1,0));

		m_pFenceGeom->AddMesh(m_pHighlightMesh, highlight_matidx);
	}
}
Esempio n. 20
0
void vtFence3d::AddFenceMeshes(vtHeightField3d *pHeightField)
{
	// Trigger the creation of any materials we may need
	GetMatIndex("");

	uint i, j;
	uint numfencepts = m_pFencePts.GetSize();

	FLine3 p3;

	FPoint3 diff, fp;
	FPoint3 PostSize(m_Params.m_fPostWidth, m_Params.m_fPostHeight,
		m_Params.m_fPostDepth);

	// All culture (roads and buildings) can be draped on
	int iIncludeCulture = CE_ALL;

	// first, project the posts from earth to world
	m_Posts3d.SetSize(numfencepts);
	for (i = 0; i < numfencepts; i++)
		pHeightField->ConvertEarthToSurfacePoint(m_pFencePts[i], m_Posts3d[i], iIncludeCulture);

	// Find highest point
	m_fMaxGroundY = -1E8;
	for (i = 0; i < numfencepts; i++)
		if (m_Posts3d[i].y > m_fMaxGroundY)
			m_fMaxGroundY = m_Posts3d[i].y;

	if (m_Params.m_PostType != "none")
	{
		// has posts
		// determine where the fence posts go
		for (i = 0; i < numfencepts; i++)
		{
			if (i == numfencepts-1)
			{
				p3.Append(m_Posts3d[i]);
				continue;
			}
			// get start and end group points for this section
			FPoint3 wpos1 = m_Posts3d[i];
			FPoint3 wpos2 = m_Posts3d[i+1];

			// look at world distance (approximate meters, _not_ earth
			//  coordinates, which might be in e.g. feet or degrees)
			diff = wpos2 - wpos1;
			float distance = sqrt(diff.x*diff.x+diff.z*diff.z);
			uint segments = (uint) (distance / m_Params.m_fPostSpacing);
			if (segments < 1) segments = 1;
			FPoint3 diff_per_segment = diff / (float) segments;

			for (j = 0; j < segments; j++)
			{
				fp = wpos1 + (diff_per_segment * (float)j);

				if (i > 0 && i < numfencepts-1)
				{
					// randomly offset by up to 4% of fence spacing, for "realism"
					fp.x += random_offset(0.04f * m_Params.m_fPostSpacing);
					fp.z += random_offset(0.04f * m_Params.m_fPostSpacing);
				}
				// false: true elevation, true: include culture (structures and roads)
				pHeightField->FindAltitudeAtPoint(fp, fp.y, false, CE_ALL);
				p3.Append(fp);
			}
		}
		// generate the posts
		// Look first for post materials (type 3)
		int iMatIdx = GetMatIndex(m_Params.m_PostType, RGBf(), 3);

		// If that didn't work, look for any material by that name
		if (iMatIdx == -1)
			int iMatIdx = GetMatIndex(m_Params.m_PostType);
		for (i = 0; i < p3.GetSize(); i++)
			AddFencepost(p3[i], iMatIdx);
	}
	else
	{
		// no post spacing to consider, so just use the input vertices
		p3.SetSize(numfencepts);
		for (i = 0; i < numfencepts; i++)
			p3[i] = m_Posts3d[i];
	}

	if (m_Params.m_PostExtension != "none")
		AddPostExtensions(p3);

	// if not enough points, nothing connections to create
	if (p3.GetSize() < 2)
		return;

	if (m_Params.m_iConnectType == 0)	// none
	{
		// nothing to do
	}
	else if (m_Params.m_iConnectType == 1)	// wire
	{
		AddWireMeshes(p3);
	}

	if (m_Params.m_ConnectMaterial == "none")
		return;

	if (m_Params.m_iConnectType == 2)	// simple
	{
		if (m_Params.m_fConnectWidth == 0.0f)
			AddFlatConnectionMesh(p3);
		else if (m_Params.m_fConnectWidth > 0.0f)
			AddThickConnectionMesh(p3);
	}
	else if (m_Params.m_iConnectType == 3)	// profile
	{
		AddProfileConnectionMesh(p3);
	}
}
Esempio n. 21
0
void SolveSpace::ExportLinesAndMesh(SEdgeList *sel, SBezierList *sbl, SMesh *sm,
                                    Vector u, Vector v, Vector n,
                                        Vector origin, double cameraTan,
                                    VectorFileWriter *out)
{
    double s = 1.0 / SS.exportScale;

    // Project into the export plane; so when we're done, z doesn't matter,
    // and x and y are what goes in the DXF.
    SEdge *e;
    for(e = sel->l.First(); e; e = sel->l.NextAfter(e)) {
        // project into the specified csys, and apply export scale
        (e->a) = e->a.InPerspective(u, v, n, origin, cameraTan).ScaledBy(s);
        (e->b) = e->b.InPerspective(u, v, n, origin, cameraTan).ScaledBy(s);
    }

    SBezier *b;
    if(sbl) {
        for(b = sbl->l.First(); b; b = sbl->l.NextAfter(b)) {
            *b = b->InPerspective(u, v, n, origin, cameraTan);
            int i;
            for(i = 0; i <= b->deg; i++) {
                b->ctrl[i] = (b->ctrl[i]).ScaledBy(s);
            }
        }
    }

    // If cutter radius compensation is requested, then perform it now
    if(fabs(SS.exportOffset) > LENGTH_EPS) {
        // assemble those edges into a polygon, and clear the edge list
        SPolygon sp;
        ZERO(&sp);
        sel->AssemblePolygon(&sp, NULL);
        sel->Clear();

        SPolygon compd;
        ZERO(&compd);
        sp.normal = Vector::From(0, 0, -1);
        sp.FixContourDirections();
        sp.OffsetInto(&compd, SS.exportOffset*s);
        sp.Clear();

        compd.MakeEdgesInto(sel);
        compd.Clear();
    }

    // Now the triangle mesh; project, then build a BSP to perform
    // occlusion testing and generated the shaded surfaces.
    SMesh smp;
    ZERO(&smp);
    if(sm) {
        Vector l0 = (SS.lightDir[0]).WithMagnitude(1),
               l1 = (SS.lightDir[1]).WithMagnitude(1);
        STriangle *tr;
        for(tr = sm->l.First(); tr; tr = sm->l.NextAfter(tr)) {
            STriangle tt = *tr;
            tt.a = (tt.a).InPerspective(u, v, n, origin, cameraTan).ScaledBy(s);
            tt.b = (tt.b).InPerspective(u, v, n, origin, cameraTan).ScaledBy(s);
            tt.c = (tt.c).InPerspective(u, v, n, origin, cameraTan).ScaledBy(s);

            // And calculate lighting for the triangle
            Vector n = tt.Normal().WithMagnitude(1);
            double lighting = SS.ambientIntensity +
                                  max(0, (SS.lightIntensity[0])*(n.Dot(l0))) +
                                  max(0, (SS.lightIntensity[1])*(n.Dot(l1)));
            double r = min(1, REDf  (tt.meta.color)*lighting),
                   g = min(1, GREENf(tt.meta.color)*lighting),
                   b = min(1, BLUEf (tt.meta.color)*lighting);
            tt.meta.color = RGBf(r, g, b);
            smp.AddTriangle(&tt);
        }
    }

    // Use the BSP routines to generate the split triangles in paint order.
    SBsp3 *bsp = SBsp3::FromMesh(&smp);
    SMesh sms;
    ZERO(&sms);
    bsp->GenerateInPaintOrder(&sms);
    // And cull the back-facing triangles
    STriangle *tr;
    sms.l.ClearTags();
    for(tr = sms.l.First(); tr; tr = sms.l.NextAfter(tr)) {
        Vector n = tr->Normal();
        if(n.z < 0) {
            tr->tag = 1;
        }
    }
    sms.l.RemoveTagged();

    // And now we perform hidden line removal if requested
    SEdgeList hlrd;
    ZERO(&hlrd);
    if(sm && !SS.GW.showHdnLines) {
        SKdNode *root = SKdNode::From(&smp);

        // Generate the edges where a curved surface turns from front-facing
        // to back-facing.
        if(SS.GW.showEdges) {
            root->MakeCertainEdgesInto(sel, SKdNode::TURNING_EDGES,
                        false, NULL, NULL);
        }

        root->ClearTags();
        int cnt = 1234;

        SEdge *se;
        for(se = sel->l.First(); se; se = sel->l.NextAfter(se)) {
            if(se->auxA == Style::CONSTRAINT) {
                // Constraints should not get hidden line removed; they're
                // always on top.
                hlrd.AddEdge(se->a, se->b, se->auxA);
                continue;
            }

            SEdgeList out;
            ZERO(&out);
            // Split the original edge against the mesh
            out.AddEdge(se->a, se->b, se->auxA);
            root->OcclusionTestLine(*se, &out, cnt);
            // the occlusion test splits unnecessarily; so fix those
            out.MergeCollinearSegments(se->a, se->b);
            cnt++;
            // And add the results to our output
            SEdge *sen;
            for(sen = out.l.First(); sen; sen = out.l.NextAfter(sen)) {
                hlrd.AddEdge(sen->a, sen->b, sen->auxA);
            }
            out.Clear();
        }

        sel = &hlrd;
    }

    // We kept the line segments and Beziers separate until now; but put them
    // all together, and also project everything into the xy plane, since not
    // all export targets ignore the z component of the points.
    for(e = sel->l.First(); e; e = sel->l.NextAfter(e)) {
        SBezier sb = SBezier::From(e->a, e->b);
        sb.auxA = e->auxA;
        sbl->l.Add(&sb);
    }
    for(b = sbl->l.First(); b; b = sbl->l.NextAfter(b)) {
        for(int i = 0; i <= b->deg; i++) {
            b->ctrl[i].z = 0;
        }
    }

    // If possible, then we will assemble these output curves into loops. They
    // will then get exported as closed paths.
    SBezierLoopSetSet sblss;
    ZERO(&sblss);
    SBezierList leftovers;
    ZERO(&leftovers);
    SSurface srf = SSurface::FromPlane(Vector::From(0, 0, 0),
                                       Vector::From(1, 0, 0),
                                       Vector::From(0, 1, 0));
    SPolygon spxyz;
    ZERO(&spxyz);
    bool allClosed;
    SEdge notClosedAt;
    sbl->l.ClearTags();
    sblss.FindOuterFacesFrom(sbl, &spxyz, &srf,
                             SS.ChordTolMm()*s,
                             &allClosed, &notClosedAt,
                             NULL, NULL,
                             &leftovers);
    for(b = leftovers.l.First(); b; b = leftovers.l.NextAfter(b)) {
        sblss.AddOpenPath(b);
    }

    // Now write the lines and triangles to the output file
    out->Output(&sblss, &sms);

    leftovers.Clear();
    spxyz.Clear();
    sblss.Clear();
    smp.Clear();
    sms.Clear();
    hlrd.Clear();
}