Fil:Sphere wireframe.svg

Fra Wikipedia, den frie encyklopædi
Gå til: navigation, søg
Sphere_wireframe.svg(SVG fil, basisstørrelse 400 × 400 punkters, størrelse: 8 KB)

Denne fil er fra Wikimedia Commons

[redigér] Beskrivelse

Beskrivelse
English: Sphere wireframe - orthogonal projection of a sphere. The image shows lines, which are drawn as they were painted onto the surface of a sphere. The angular distance between two lines is 10°. The SVG file is created by the below C++-program, which calculates each edge of a line as an ellipse-bow. The backside of the sphere has an opacity of 0.25. The axis tilt is 52.5°.
Dato november 2008(2008-11)
Kilde Eget arbejde
Ophavsmand Geek3
Andre versioner

Sphere filled_blue.svg
Sphere wireframe 10deg 10r.svg

[redigér] Source Code

This image can be completely generated by the following source code. If you have the gnu compiler collection installed, the image can be compiled by the following commands:

g++ sphere_wireframe.cpp -o sphere_wireframe
./sphere_wireframe > Sphere_wireframe.svg
rsvg-view Sphere_wireframe.svg

sphere_wireframe.cpp:

/* sphere - creates a svg vector-graphics file which depicts a wireframe sphere
 *
 * Copyright (C) 2008 Wikimedia foundation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can either send email to this
 * program's author (see below) or write to:
 *   The Free Software Foundation, Inc.
 *   51 Franklin Street, Fifth Floor
 *   Boston, MA 02110-1301  USA
 */
 
/* The expressions in this code are not proven to be correct.
 * Hence this code probably contains lots of bugs. Be aware! */
 
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <cstring>
 
using namespace std;
 
const double PI = 3.1415926535897932;
const double DEG = PI / 180.0;
 
/********************************* settings **********************************/
int n_lon = 18;                         // number of latitude fields (18 => 10° each)
int n_lat = 18;                         // half number of longitude fields (18 => 10° each)
double lon_offset = 2.5 * DEG;  // offset of the meridians
double w = 52.5 * DEG;          // axial tilt (0° => axis is perpendicular to image plane)
double stripe_grad = 0.5 * DEG; // width of each line
int image_size = 400;                   // width and height of the image in pixels
double back_opacity = 0.25;             // opacity of the sphere's backside
char color[] = "#334070";               // color of lines
int istep = 2;                  // svg code indentation step
/*****************************************************************************/
 
double sqr(double x)
{
        return(x * x);
}
 
// commands for svg-code:
void indent(int n, bool in_tag = false)
{
        n *= istep;
        if (in_tag) n += istep + 1;
        for (int i = 0; i < n; i++) cout << " ";
}
void M()
{
        cout << "M ";
}
void Z()
{
        cout << "Z ";
}
void xy(double x, double y)
{
        cout << x << ",";
        cout << y << " ";
}
void arc(double a, double b, double x_axis_rot, bool large_arc, bool sweep)
{       // draws an elliptic arc
        if (b < 0.5E-6)
        {       // flat ellipses are not rendered properly => use line
                cout << "L ";
        }
        else
        {
                cout << "A ";
                cout << a << ",";       // semi-major axis
                cout << b << " ";       // semi-minor axis
                cout << x_axis_rot << " ";
                cout << large_arc << " ";
                cout << sweep << " ";
        }
}
void circle(bool clockwise)
{
        M();
        xy(-1, 0);
        arc(1, 1, 0, 0, !clockwise);
        xy(1, 0);
        arc(1, 1, 0, 0, !clockwise);
        xy(-1, 0);
        Z();
}
 
void start_svg_file()
{
        cout << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n";
        cout << "<svg id=\"Sphere_wireframe\"\n";
        cout << "  version=\"1.1\"\n";
        cout << "  baseProfile=\"full\"\n";
        cout << "  xmlns=\"http://www.w3.org/2000/svg\"\n";
        cout << "  xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n";
        cout << "  width=\"" << image_size << "\"\n";
        cout << "  height=\"" << image_size << "\">\n\n";
        cout << "  <title>Sphere wireframe</title>\n\n";
        cout << "  <desc>\n";
        cout << "     about: http://commons.wikimedia.org/wiki/Image:Sphere_wireframe.svg\n";
        cout << "     rights: GNU Free Documentation license,\n";
        cout << "             Creative Commons Attribution ShareAlike license\n";
        cout << "  </desc>\n\n";
        cout << "  <g id=\"sphere\" transform=\"scale(" << 0.5 * image_size;
        cout << ", " << -0.5 * image_size << ") translate(1, -1)\">\n";
}
 
void end_svg_file()
{
        cout << "  </g>\n</svg>\n";
}
 
 
 
int main (int argc, char *argv[])
{
        // accept -lat and -lon as parameter
        for (int i = 2; i < argc; i++)
        {
                if (isdigit(argv[i][0]) || (sizeof(argv[i]) > sizeof(char)
                        && isdigit(argv[i][1])
                        && (argv[i][0] == '.' || argv[i][0] == '-')))
                {
                        if (strcmp(argv[i - 1], "-lon") == 0)
                        {
                                lon_offset = atof(argv[i]) * DEG;
                        }
                        if (strcmp(argv[i - 1], "-lat") == 0)
                        {
                                w = atof(argv[i]) * DEG;
                        }
                }
        }
        double cosw = cos(w), sinw = sin(w);
        double d = 0.5 * stripe_grad;
 
        start_svg_file();
        int ind = 2; // initial indentation level
        indent(ind);
        cout << "<g id=\"sphere_back\" transform=\"rotate(180)\" ";
        cout << "opacity=\"" << back_opacity << "\">\n";
        indent(++ind);
        cout << "<g id=\"sphere_half\">\n";
 
        // meridians
        indent(++ind); cout << "<g id=\"meridians\"\n";
        indent(ind++, true);
        cout << "style=\"stroke:none; fill:" << color << "; fill_rule:evenodd\">\n";
        double a = abs(cos(d));
        for (int i_lon = 0; i_lon < n_lat; i_lon++)
        {       // draw one meridian
                double longitude = lon_offset + (i_lon * 180.0 / n_lat) * DEG;
                double lon[2];
                lon[0] = longitude + d;
                lon[1] = longitude - d;
 
                indent(ind);
                cout << "<path id=\"meridian";
                cout << i_lon << "\"\n";
                indent(ind, true);
                cout << "d=\"";
 
                double axis_rot = atan2(-1.0 / tan(longitude), cosw);
                if (sinw < 0)
                        axis_rot += PI;
                double w2 = sin(longitude) * sinw;
                double b = abs(w2 * cos(d));
 
                double sinw1 = sin(d) / sqrt(1.0 - sqr(sin(longitude) * sinw));
 
                if (abs(sinw1) >= 1.0)
                {       // stripe covers edge of the circle
                        double w3 = sqrt(1.0 - sqr(w2)) * sin(d);
                        circle(false);
                        // ellipse
                        M();
                        xy(sin(axis_rot) * w3 - cos(axis_rot) * a,
                                -cos(axis_rot) * w3 - sin(axis_rot) * a);
                        arc(a, b, axis_rot / DEG, 0, 0);
                        xy(sin(axis_rot) * w3 + cos(axis_rot) * a,
                                -cos(axis_rot) * w3 + sin(axis_rot) * a);
                        arc(a, b, axis_rot / DEG, 0, 0);
                        xy(sin(axis_rot) * w3 - cos(axis_rot) * a,
                                -cos(axis_rot) * w3 - sin(axis_rot) * a);
                        Z();
                }
                else
                {       // draw a disrupted ellipse bow
                        double w1 = asin(sinw1);
                        M();
                        xy(-cos(axis_rot + w1), -sin(axis_rot + w1));
                        arc(a, b, axis_rot / DEG, 1, 0);
                        xy(cos(axis_rot - w1), sin(axis_rot - w1));
                        arc(1, 1, 0, 0, 1);
                        xy(cos(axis_rot + w1), sin(axis_rot + w1));
                        arc(a, b, axis_rot / DEG, 0, 1);
                        xy(-cos(axis_rot - w1), -sin(axis_rot - w1));
                        arc(1, 1, 0, 0, 1);
                        xy(-cos(axis_rot + w1), -sin(axis_rot + w1));
                }
                Z();
                cout << "\" />\n";
        }
        indent(--ind); cout << "</g>\n";
 
        cout << endl;
 
        // circles of latitude
        indent(ind); cout << "<g id=\"circles_of_latitude\"\n";
        indent(ind, true);
        cout << "style=\"stroke:none; fill:" << color << "; fill_rule:evenodd\">\n";
        ind++;
        for (int i_lat = 1; i_lat < n_lon; i_lat++)
        {       // draw one circle of latitude
                double latitude = (i_lat * 180.0 / n_lon - 90.0) * DEG;
                double lat[2];
                lat[0] = latitude + d;
                lat[1] = latitude - d;
                double x[2], yd[2], ym[2];
                for (int i = 0; i < 2; i++)
                {
                        x[i] = abs(cos(lat[i]));
                        yd[i] = abs(cosw * cos(lat[i]));
                        ym[i] = sinw * sin(lat[i]);
                }
                double h[4];    // height of each point above image plane
                h[0] = sin(lat[0] + w);
                h[1] = sin(lat[0] - w);
                h[2] = sin(lat[1] + w);
                h[3] = sin(lat[1] - w);
 
                if (h[0] > 0 || h[1] > 0 || h[2] > 0 || h[3] > 0)
                {       // at least any part visible
                        indent(ind);
                        cout << "<path id=\"circle_of_latitude";
                        cout << i_lat << "\"\n";
                        indent(ind, true);
                        cout << "d=\"";
                        for (int i = 0; i < 2; i++)
                        {
                                if ((h[2*i] >= 0 && h[2*i+1] >= 0)
                                        && (h[2*i] > 0 || h[2*i+1] > 0))
                                {       // complete ellipse
                                        M();
                                        xy(-x[i], ym[i]); // startpoint
                                        for (int z = 1; z > -2; z -= 2)
                                        {
                                                arc(x[i], yd[i], 0, 1, i);
                                                xy(z * x[i], ym[i]);
                                        }
                                        Z();
                                        if (h[2-2*i] * h[3-2*i] < 0)
                                        {       // partly ellipse + partly circle
                                                double yp = sin(lat[1-i]) / sinw;
                                                double xp = sqrt(1.0 - sqr(yp));
                                                if (sinw < 0)
                                                {
                                                        xp = -xp;
                                                }
                                                M();
                                                xy(-xp, yp);
                                                arc(x[1-i], yd[1-i], 0,
                                                        sin(lat[1-i]) * cosw > 0, cosw >= 0);
                                                xy(xp, yp);
                                                arc(1, 1, 0, 0, cosw >= 0);
                                                xy(-xp, yp);
                                                Z();
                                        }
                                        else if (h[2-2*i] <= 0 && h[3-2*i] <= 0)
                                        {       // stripe covers edge of the circle
                                                circle(cosw < 0);
                                        }
                                }
                        }
 
                        if ((h[0] * h[1] < 0 && h[2] <= 0 && h[3] <= 0)
                                || (h[0] <= 0 && h[1] <= 0 && h[2] * h[3] < 0))
                        {
                                // one slice visible
                                int i = h[0] <= 0 && h[1] <= 0;
                                double yp = sin(lat[i]) / sinw;
                                double xp = sqrt(1.0 - yp * yp);
                                M();
                                xy(-xp, yp);
                                arc(x[i], yd[i], 0, sin(lat[i]) * cosw > 0, cosw * sinw >= 0);
                                xy(xp, yp);
                                arc(1, 1, 0, 0, cosw * sinw < 0);
                                xy(-xp, yp);
                                Z();
                        }
                        else if (h[0] * h[1] < 0 && h[2] * h[3] < 0)
                        {
                                // disrupted ellipse bow
                                double xp[2], yp[2];
                                for (int i = 0; i < 2; i++)
                                {
                                        yp[i] = sin(lat[i]) / sinw;
                                        xp[i] = sqrt(1.0 - sqr(yp[i]));
                                        if (sinw < 0) xp[i] = -xp[i];
                                }
                                M();
                                xy(-xp[0], yp[0]);
                                arc(x[0], yd[0], 0, sin(lat[0]) * cosw > 0, cosw >= 0);
                                xy(xp[0], yp[0]);
                                arc(1, 1, 0, 0, 0);
                                xy(xp[1], yp[1]);
                                arc(x[1], yd[1], 0, sin(lat[1]) * cosw > 0, cosw < 0);
                                xy(-xp[1], yp[1]);
                                arc(1, 1, 0, 0, 0);
                                xy(-xp[0], yp[0]);
                                Z();
                        }
                        cout << "\" />\n";
                }
        }
        for (int i = 0; i < 3; i++)
        {
                indent(--ind);
                cout << "</g>\n";
        }
        indent(ind--);
        cout << "<use id=\"sphere_front\" xlink:href=\"#sphere_half\" />\n";
        end_svg_file();
}


[redigér] Licens

Jeg, dette værks ophavsretsindehaver, udgiver hermed værket under den følgende licens:
GNU head Tilladelse er givet til at kopiere, distribuere og/eller ændre dette dokument under betingelserne i GNU Free Documentation License', Version 1.2 eller enhver senere version udgivet af Free Software Foundation; uden et invariant afsnit, forsidetekster, og ingen bagsidetekst. En kopi af licensen er inkluderet i afsnittet GNU Free Documentation License.

w:da:Creative Commons
navngivelse del på samme vilkår
Denne fil er udgivet under Creative Commons Navngivelse – Del på samme vilkår 3.0 Unported, 2.5 Generisk, 2.0 Generisk og 1.0 Generisk-licensen.
Du har frihed til:
  • til at dele – til at fremstille eksemplarer og gøre værket tilgængeligt for almenheden
  • til at fremstille bearbejdede værker – til at fremstille bearbejdede værker
På følgende vilkår:
  • navngivelse – Du skal kreditere værket på den måde, der er angivet af rettighedshaveren og licensgiveren.
  • del på samme vilkår – Hvis du bearbejder, herunder ændrer og tilpasser, dette værk, herunder også med kommercielt sigte, skal du licensere det nye værk under tilsvarende vilkår.

Du må anvende din foretrukne licens.

Filhistorik

Klik på en dato/tid for at se den version af filen.

Dato/tidThumbnailDimensionerBrugerKommentar
nuværende23. nov 2008, 18:10Thumbnail af versionen fra 23. nov 2008, 18:10400 × 400 (8 KB)Geek3{{Information |Description={{en|1=Sphere wireframe - the image shows lines, which are drawn as they were painted onto the surface of a sphere. The distance between two lines is 10°. The svg file is created by the below c++-program, which calculates each

Den følgende side henviser til denne fil:

Global filanvendelse

Følgende andre wikier anvender denne fil:

Metadata

Personlige værktøjer
Navnerum

Varianter
Visninger
Handlinger
Navigation
Deltagelse
Værktøjer
Organisation