void PdfFileWriter::StartPath(RgbColor strokeRgb, double lineWidth,
                              bool filled, RgbColor fillRgb)
{
    fprintf(f, "1 J 1 j " // round endcaps and joins
               "%.3f w "
               "%.3f %.3f %.3f RG\r\n",
        MmToPts(lineWidth),
        strokeRgb.redF(), strokeRgb.greenF(), strokeRgb.blueF());
    if(filled) {
        fprintf(f, "%.3f %.3f %.3f rg\r\n",
            fillRgb.redF(), fillRgb.greenF(), fillRgb.blueF());
    }

    prevPt = Vector::From(VERY_POSITIVE, VERY_POSITIVE, VERY_POSITIVE);
}
Exemple #2
0
void GraphicsWindow::Selection::Draw(void) {
    Vector refp = Vector::From(0, 0, 0);
    if(entity.v) {
        Entity *e = SK.GetEntity(entity);
        e->Draw();
        if(emphasized) refp = e->GetReferencePos();
    }
    if(constraint.v) {
        Constraint *c = SK.GetConstraint(constraint);
        c->Draw();
        if(emphasized) refp = c->GetReferencePos();
    }
    if(emphasized && (constraint.v || entity.v)) {
        // We want to emphasize this constraint or entity, by drawing a thick
        // line from the top left corner of the screen to the reference point
        // of that entity or constraint.
        double s = 0.501/SS.GW.scale;
        Vector topLeft =       SS.GW.projRight.ScaledBy(-SS.GW.width*s);
        topLeft = topLeft.Plus(SS.GW.projUp.ScaledBy(SS.GW.height*s));
        topLeft = topLeft.Minus(SS.GW.offset);

        glLineWidth(40);
        RgbColor rgb = Style::Color(Style::HOVERED);
        glColor4d(rgb.redF(), rgb.greenF(), rgb.blueF(), 0.2);
        glBegin(GL_LINES);
            ssglVertex3v(topLeft);
            ssglVertex3v(refp);
        glEnd();
        glLineWidth(1);
    }
}
void EpsFileWriter::FinishPath(RgbColor strokeRgb, double lineWidth,
                               bool filled, RgbColor fillRgb)
{
    fprintf(f, "    %.3f setlinewidth\r\n"
               "    %.3f %.3f %.3f setrgbcolor\r\n"
               "    1 setlinejoin\r\n"  // rounded
               "    1 setlinecap\r\n"   // rounded
               "    gsave stroke grestore\r\n",
        MmToPts(lineWidth),
        strokeRgb.redF(), strokeRgb.greenF(), strokeRgb.blueF());
    if(filled) {
        fprintf(f, "    %.3f %.3f %.3f setrgbcolor\r\n"
                   "    gsave fill grestore\r\n",
            fillRgb.redF(), fillRgb.greenF(), fillRgb.blueF());
    }
}
Exemple #4
0
//-----------------------------------------------------------------------------
// If a color is almost white, then we can rewrite it to black, just so that
// it won't disappear on file formats with a light background.
//-----------------------------------------------------------------------------
RgbColor Style::RewriteColor(RgbColor rgbin) {
    Vector rgb = Vector::From(rgbin.redF(), rgbin.greenF(), rgbin.blueF());
    rgb = rgb.Minus(Vector::From(1, 1, 1));
    if(rgb.Magnitude() < 0.4 && SS.fixExportColors) {
        // This is an almost-white color in a default style, which is
        // good for the default on-screen view (black bg) but probably
        // not desired in the exported files, which typically are shown
        // against white backgrounds.
        return RGBi(0, 0, 0);
    } else {
        return rgbin;
    }
}
Exemple #5
0
void TextWindow::ShowListOfStyles(void) {
    Printf(true, "%Ft color  style-name");

    bool darkbg = false;
    Style *s;
    for(s = SK.style.First(); s; s = SK.style.NextAfter(s)) {
        Printf(false, "%Bp  %Bz   %Bp   %Fl%Ll%f%D%s%E",
            darkbg ? 'd' : 'a',
            &s->color,
            darkbg ? 'd' : 'a',
            ScreenShowStyleInfo, s->h.v,
            s->DescriptionString());

        darkbg = !darkbg;
    }

    Printf(true, "  %Fl%Ll%fcreate a new custom style%E",
        &ScreenCreateCustomStyle);

    Printf(false, "");

    RgbColor rgb = SS.backgroundColor;
    Printf(false, "%Ft background color (r, g, b)%E");
    Printf(false, "%Ba   %@, %@, %@ %Fl%D%f%Ll[change]%E",
        rgb.redF(), rgb.greenF(), rgb.blueF(),
        top[rows-1] + 2, &ScreenChangeBackgroundColor);

    Printf(false, "");
    Printf(false, "%Ft background bitmap image%E");
    if(SS.bgImage.fromFile) {
        Printf(false, "%Ba   %Ftwidth:%E %dpx   %Ftheight:%E %dpx",
            SS.bgImage.w, SS.bgImage.h);

        Printf(false, "   %Ftscale:%E %# px/%s %Fl%Ll%f%D[change]%E",
            SS.bgImage.scale*SS.MmPerUnit(),
            SS.UnitName(),
            &ScreenChangeBackgroundImageScale, top[rows-1] + 2);

        Printf(false, "%Ba   %Fl%Lc%fclear background image%E",
            &ScreenBackgroundImage);
    } else {
        Printf(false, "%Ba   none - %Fl%Ll%fload background image%E",
            &ScreenBackgroundImage);
        Printf(false, "   (bottom left will be center of view)");
    }

    Printf(false, "");
    Printf(false, "  %Fl%Ll%fload factory defaults%E",
        &ScreenLoadFactoryDefaultStyles);
}
Exemple #6
0
void GraphicsWindow::Paint(void) {
    int i;
    havePainted = true;

    int w, h;
    GetGraphicsWindowSize(&w, &h);
    width = w; height = h;
    glViewport(0, 0, w, h);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glScaled(scale*2.0/w, scale*2.0/h, scale*1.0/30000);

    double mat[16];
    // Last thing before display is to apply the perspective
    double clp = SS.CameraTangent()*scale;
    MakeMatrix(mat, 1,              0,              0,              0,
                    0,              1,              0,              0,
                    0,              0,              1,              0,
                    0,              0,              clp,            1);
    glMultMatrixd(mat);
    // Before that, we apply the rotation
    Vector n = projUp.Cross(projRight);
    MakeMatrix(mat, projRight.x,    projRight.y,    projRight.z,    0,
                    projUp.x,       projUp.y,       projUp.z,       0,
                    n.x,            n.y,            n.z,            0,
                    0,              0,              0,              1);
    glMultMatrixd(mat);
    // And before that, the translation
    MakeMatrix(mat, 1,              0,              0,              offset.x,
                    0,              1,              0,              offset.y,
                    0,              0,              1,              offset.z,
                    0,              0,              0,              1);
    glMultMatrixd(mat);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glShadeModel(GL_SMOOTH);

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
    glEnable(GL_LINE_SMOOTH);
    // don't enable GL_POLYGON_SMOOTH; that looks ugly on some graphics cards,
    // drawn with leaks in the mesh
    glEnable(GL_POLYGON_OFFSET_LINE);
    glEnable(GL_POLYGON_OFFSET_FILL);
    glEnable(GL_DEPTH_TEST);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    glEnable(GL_NORMALIZE);

    // At the same depth, we want later lines drawn over earlier.
    glDepthFunc(GL_LEQUAL);

    if(SS.AllGroupsOkay()) {
        glClearColor(SS.backgroundColor.redF(),
                     SS.backgroundColor.greenF(),
                     SS.backgroundColor.blueF(), 1.0f);
    } else {
        // Draw a different background whenever we're having solve problems.
        RgbColor rgb = Style::Color(Style::DRAW_ERROR);
        glClearColor(0.4f*rgb.redF(), 0.4f*rgb.greenF(), 0.4f*rgb.blueF(), 1.0f);
        // And show the text window, which has info to debug it
        ForceTextWindowShown();
    }
    glClear(GL_COLOR_BUFFER_BIT);
    glClearDepth(1.0);
    glClear(GL_DEPTH_BUFFER_BIT);

    if(SS.bgImage.fromFile) {
        // If a background image is loaded, then we draw it now as a texture.
        // This handles the resizing for us nicely.
        glBindTexture(GL_TEXTURE_2D, TEXTURE_BACKGROUND_IMG);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     GL_CLAMP);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
                     SS.bgImage.rw, SS.bgImage.rh,
                     0,
                     GL_RGB, GL_UNSIGNED_BYTE,
                     SS.bgImage.fromFile);

        double tw = ((double)SS.bgImage.w) / SS.bgImage.rw,
               th = ((double)SS.bgImage.h) / SS.bgImage.rh;

        double mmw = SS.bgImage.w / SS.bgImage.scale,
               mmh = SS.bgImage.h / SS.bgImage.scale;

        Vector origin = SS.bgImage.origin;
        origin = origin.DotInToCsys(projRight, projUp, n);
        // Place the depth of our origin at the point that corresponds to
        // w = 1, so that it's unaffected by perspective.
        origin.z = (offset.ScaledBy(-1)).Dot(n);
        origin = origin.ScaleOutOfCsys(projRight, projUp, n);

        // Place the background at the very back of the Z order, though, by
        // mucking with the depth range.
        glDepthRange(1, 1);
        glEnable(GL_TEXTURE_2D);
        glBegin(GL_QUADS);
            glTexCoord2d(0, 0);
            ssglVertex3v(origin);

            glTexCoord2d(0, th);
            ssglVertex3v(origin.Plus(projUp.ScaledBy(mmh)));

            glTexCoord2d(tw, th);
            ssglVertex3v(origin.Plus(projRight.ScaledBy(mmw).Plus(
                                     projUp.   ScaledBy(mmh))));

            glTexCoord2d(tw, 0);
            ssglVertex3v(origin.Plus(projRight.ScaledBy(mmw)));
        glEnd();
        glDisable(GL_TEXTURE_2D);
    }
    ssglDepthRangeOffset(0);

    // Nasty case when we're reloading the imported files; could be that
    // we get an error, so a dialog pops up, and a message loop starts, and
    // we have to get called to paint ourselves. If the sketch is screwed
    // up, then we could trigger an oops trying to draw.
    if(!SS.allConsistent) return;

    // Let's use two lights, at the user-specified locations
    GLfloat f;
    glEnable(GL_LIGHT0);
    f = (GLfloat)SS.lightIntensity[0];
    GLfloat li0[] = { f, f, f, 1.0f };
    glLightfv(GL_LIGHT0, GL_DIFFUSE, li0);
    glLightfv(GL_LIGHT0, GL_SPECULAR, li0);

    glEnable(GL_LIGHT1);
    f = (GLfloat)SS.lightIntensity[1];
    GLfloat li1[] = { f, f, f, 1.0f };
    glLightfv(GL_LIGHT1, GL_DIFFUSE, li1);
    glLightfv(GL_LIGHT1, GL_SPECULAR, li1);

    Vector ld;
    ld = VectorFromProjs(SS.lightDir[0]);
    GLfloat ld0[4] = { (GLfloat)ld.x, (GLfloat)ld.y, (GLfloat)ld.z, 0 };
    glLightfv(GL_LIGHT0, GL_POSITION, ld0);
    ld = VectorFromProjs(SS.lightDir[1]);
    GLfloat ld1[4] = { (GLfloat)ld.x, (GLfloat)ld.y, (GLfloat)ld.z, 0 };
    glLightfv(GL_LIGHT1, GL_POSITION, ld1);

    if(SS.drawBackFaces) {
        // For debugging, draw the backs of the triangles in red, so that we
        // notice when a shell is open
        glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1);
    } else {
        glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 0);
    }

    GLfloat ambient[4] = { (float)SS.ambientIntensity,
                           (float)SS.ambientIntensity,
                           (float)SS.ambientIntensity, 1 };
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);

    ssglUnlockColor();

    if(showSnapGrid && LockedInWorkplane()) {
        hEntity he = ActiveWorkplane();
        EntityBase *wrkpl = SK.GetEntity(he),
                   *norm  = wrkpl->Normal();
        Vector wu, wv, wn, wp;
        wp = SK.GetEntity(wrkpl->point[0])->PointGetNum();
        wu = norm->NormalU();
        wv = norm->NormalV();
        wn = norm->NormalN();

        double g = SS.gridSpacing;

        double umin = VERY_POSITIVE, umax = VERY_NEGATIVE,
               vmin = VERY_POSITIVE, vmax = VERY_NEGATIVE;
        int a;
        for(a = 0; a < 4; a++) {
            // Ideally, we would just do +/- half the width and height; but
            // allow some extra slop for rounding.
            Vector horiz = projRight.ScaledBy((0.6*width)/scale  + 2*g),
                   vert  = projUp.   ScaledBy((0.6*height)/scale + 2*g);
            if(a == 2 || a == 3) horiz = horiz.ScaledBy(-1);
            if(a == 1 || a == 3) vert  = vert. ScaledBy(-1);
            Vector tp = horiz.Plus(vert).Minus(offset);

            // Project the point into our grid plane, normal to the screen
            // (not to the grid plane). If the plane is on edge then this is
            // impossible so don't try to draw the grid.
            bool parallel;
            Vector tpp = Vector::AtIntersectionOfPlaneAndLine(
                                            wn, wn.Dot(wp),
                                            tp, tp.Plus(n),
                                            &parallel);
            if(parallel) goto nogrid;

            tpp = tpp.Minus(wp);
            double uu = tpp.Dot(wu),
                   vv = tpp.Dot(wv);

            umin = min(uu, umin);
            umax = max(uu, umax);
            vmin = min(vv, vmin);
            vmax = max(vv, vmax);
        }

        int i, j, i0, i1, j0, j1;

        i0 = (int)(umin / g);
        i1 = (int)(umax / g);
        j0 = (int)(vmin / g);
        j1 = (int)(vmax / g);

        if(i0 > i1 || i1 - i0 > 400) goto nogrid;
        if(j0 > j1 || j1 - j0 > 400) goto nogrid;

        glLineWidth(1);
        ssglColorRGBa(Style::Color(Style::DATUM), 0.3);
        glBegin(GL_LINES);
        for(i = i0 + 1; i < i1; i++) {
            ssglVertex3v(wp.Plus(wu.ScaledBy(i*g)).Plus(wv.ScaledBy(j0*g)));
            ssglVertex3v(wp.Plus(wu.ScaledBy(i*g)).Plus(wv.ScaledBy(j1*g)));
        }
        for(j = j0 + 1; j < j1; j++) {
            ssglVertex3v(wp.Plus(wu.ScaledBy(i0*g)).Plus(wv.ScaledBy(j*g)));
            ssglVertex3v(wp.Plus(wu.ScaledBy(i1*g)).Plus(wv.ScaledBy(j*g)));
        }
        glEnd();

        // Clear the depth buffer, so that the grid is at the very back of
        // the Z order.
        glClear(GL_DEPTH_BUFFER_BIT);
nogrid:;
    }

    // Draw the active group; this does stuff like the mesh and edges.
    (SK.GetGroup(activeGroup))->Draw();

    // Now draw the entities
    if(showHdnLines) glDisable(GL_DEPTH_TEST);
    Entity::DrawAll();

    // Draw filled paths in all groups, when those filled paths were requested
    // specially by assigning a style with a fill color, or when the filled
    // paths are just being filled by default. This should go last, to make
    // the transparency work.
    Group *g;
    for(g = SK.group.First(); g; g = SK.group.NextAfter(g)) {
        if(!(g->IsVisible())) continue;
        g->DrawFilledPaths();
    }


    glDisable(GL_DEPTH_TEST);
    // Draw the constraints
    for(i = 0; i < SK.constraint.n; i++) {
        SK.constraint.elem[i].Draw();
    }

    // Draw the traced path, if one exists
    glLineWidth(Style::Width(Style::ANALYZE));
    ssglColorRGB(Style::Color(Style::ANALYZE));
    SContour *sc = &(SS.traced.path);
    glBegin(GL_LINE_STRIP);
    for(i = 0; i < sc->l.n; i++) {
        ssglVertex3v(sc->l.elem[i].p);
    }
    glEnd();

    // And the naked edges, if the user did Analyze -> Show Naked Edges.
    glLineWidth(Style::Width(Style::DRAW_ERROR));
    ssglColorRGB(Style::Color(Style::DRAW_ERROR));
    ssglDrawEdges(&(SS.nakedEdges), true);

    // Then redraw whatever the mouse is hovering over, highlighted.
    glDisable(GL_DEPTH_TEST);
    ssglLockColorTo(Style::Color(Style::HOVERED));
    hover.Draw();

    // And finally draw the selection, same mechanism.
    ssglLockColorTo(Style::Color(Style::SELECTED));
    for(Selection *s = selection.First(); s; s = selection.NextAfter(s)) {
        s->Draw();
    }

    ssglUnlockColor();

    // If a marquee selection is in progress, then draw the selection
    // rectangle, as an outline and a transparent fill.
    if(pending.operation == DRAGGING_MARQUEE) {
        Point2d begin = ProjectPoint(orig.marqueePoint);
        double xmin = min(orig.mouse.x, begin.x),
               xmax = max(orig.mouse.x, begin.x),
               ymin = min(orig.mouse.y, begin.y),
               ymax = max(orig.mouse.y, begin.y);

        Vector tl = UnProjectPoint(Point2d::From(xmin, ymin)),
               tr = UnProjectPoint(Point2d::From(xmax, ymin)),
               br = UnProjectPoint(Point2d::From(xmax, ymax)),
               bl = UnProjectPoint(Point2d::From(xmin, ymax));

        glLineWidth((GLfloat)1.3);
        ssglColorRGB(Style::Color(Style::HOVERED));
        glBegin(GL_LINE_LOOP);
            ssglVertex3v(tl);
            ssglVertex3v(tr);
            ssglVertex3v(br);
            ssglVertex3v(bl);
        glEnd();
        ssglColorRGBa(Style::Color(Style::HOVERED), 0.10);
        glBegin(GL_QUADS);
            ssglVertex3v(tl);
            ssglVertex3v(tr);
            ssglVertex3v(br);
            ssglVertex3v(bl);
        glEnd();
    }

    // An extra line, used to indicate the origin when rotating within the
    // plane of the monitor.
    if(SS.extraLine.draw) {
        glLineWidth(1);
        ssglLockColorTo(Style::Color(Style::DATUM));
        glBegin(GL_LINES);
            ssglVertex3v(SS.extraLine.ptA);
            ssglVertex3v(SS.extraLine.ptB);
        glEnd();
    }

    // A note to indicate the origin in the just-exported file.
    if(SS.justExportedInfo.draw) {
        ssglColorRGB(Style::Color(Style::DATUM));
        Vector p = SS.justExportedInfo.pt,
               u = SS.justExportedInfo.u,
               v = SS.justExportedInfo.v;

        glLineWidth(1.5);
        glBegin(GL_LINES);
            ssglVertex3v(p.Plus(u.WithMagnitude(-15/scale)));
            ssglVertex3v(p.Plus(u.WithMagnitude(30/scale)));
            ssglVertex3v(p.Plus(v.WithMagnitude(-15/scale)));
            ssglVertex3v(p.Plus(v.WithMagnitude(30/scale)));
        glEnd();

        ssglWriteText("(x, y) = (0, 0) for file just exported",
            DEFAULT_TEXT_HEIGHT,
            p.Plus(u.ScaledBy(10/scale)).Plus(v.ScaledBy(10/scale)),
            u, v, NULL, NULL);
        ssglWriteText("press Esc to clear this message",
            DEFAULT_TEXT_HEIGHT,
            p.Plus(u.ScaledBy(40/scale)).Plus(
                   v.ScaledBy(-(DEFAULT_TEXT_HEIGHT)/scale)),
            u, v, NULL, NULL);
    }

    // And finally the toolbar.
    if(SS.showToolbar) {
        ToolbarDraw();
    }
}
Exemple #7
0
void ssglColorRGBa(RgbColor rgb, double a)
{
    if(!ColorLocked) glColor4d(rgb.redF(), rgb.greenF(), rgb.blueF(), a);
}
Exemple #8
0
void ssglLockColorTo(RgbColor rgb)
{
    ColorLocked = false;
    glColor3d(rgb.redF(), rgb.greenF(), rgb.blueF());
    ColorLocked = true;
}