home *** CD-ROM | disk | FTP | other *** search
- From: allen@viewlogic.com (Dave Allen)
- Newsgroups: comp.sources.misc
- Subject: REPOST: v18i003: planet - planet generation simulator, Part03/04
- Message-ID: <1991Apr9.041754.8090@sparky.IMD.Sterling.COM>
- Date: 9 Apr 91 04:17:54 GMT
- Approved: kent@sparky.imd.sterling.com
- X-Checksum-Snefru: 9e87f929 1fb6a493 125dafc0 59ca8a0d
-
- Submitted-by: Dave Allen <allen@viewlogic.com>
- Posting-number: Volume 18, Issue 3
- Archive-name: planet/part03
- Supersedes: tec: Volume 10, Issue 77-78
-
- #! /bin/sh
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: ./doc/about.tec ./src/clim.c ./src/heat.c ./src/pressure.c
- # ./src/tec1.c ./src/x.c
- # Wrapped by kent@sparky on Mon Apr 8 22:39:15 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 3 (of 4)."'
- if test -f './doc/about.tec' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./doc/about.tec'\"
- else
- echo shar: Extracting \"'./doc/about.tec'\" \(10300 characters\)
- sed "s/^X//" >'./doc/about.tec' <<'END_OF_FILE'
- XI. MOTIVATION AND APPROACH
- X
- XI wanted to write a program to generate maps of many imaginary worlds using
- Xa microcomputer. Fractal techniques produce unacceptably random-looking maps.
- XIn other related fields, people have used simplified models of physical
- Xprocesses and then tweaked the model parameters to give results that "looked
- Xright". Dole [1] simulated accretion of planets around stars. Hart [2]
- Xsimulated the evolution of a planetary atmosphere. Forrester [3] simulated
- Xpopulation dynamics for near-future Earth. My approach was to find a physical
- Xmodel for continent formation, and then write a program to implement that model.
- X
- XGeologists have proposed [4] that several times in history, the continents
- Xof Earth have drifted together to form a single "supercontinent", which later
- Xbroke apart. A recent paper [5] suggested a physical model for this
- X"supercontinent cycle", and I used that model for my program.
- X
- XTheir hypothesis runs like this. (Disclaimer - I don't know anything about
- Xgeology except what I got from reading a few papers.) The Earth generates
- Xheat by radioactive decay; this heat is conducted away more slowly by
- Xcontinental crust than by oceanic crust. Heat accumulates under large
- Xcontinents, causing them to dome upwards and eventually break apart. After
- Xa certain amount of heat has escaped through the new ocean basin, the
- Xcontinental fragments are drawn back together by the subsiding basin.
- XOver long periods of time, many oceans should open and close in the center
- Xof the land area, while the original superocean should remain about the same.
- X
- XAny map of the Earth shows evidence to support this hypothesis. The Atlantic
- Xand Mediterranean oceans are fairly recent, while the Pacific could be
- Xconsidered the superocean. The Himalayas, the Pyrenees, and the Ukraine
- Xmountain ranges could have been formed by collisions between continental
- Xfragments. The "Ring of Fire" around the Pacific represents subduction zones
- Xwhere new mountains, such as the Rockies, are forming as the continents drift
- Xfurther apart. The older, lower Appalachian mountains might have been created
- Xduring a collision between Europe and North America in the last supercontinent
- Xcycle.
- X
- X
- XII. REPRESENTATION
- X
- XOne data structure well-suited for storing topographic maps is a simple
- Xtwo-dimensional array, where each array element represents the height
- Xof the terrain at that point. However, the Earth is spherical and a sphere
- Xcan't be mapped onto a plane without some distortion. After trying many
- Xmapping methods, I came back to the simplest: I pretend Columbus was wrong,
- Xand the world really is flat. Since the continents in the physical model
- Xdrift toward and away from some central point, it is reasonable, if the map
- Xis large enough, to simply throw away the land area that falls off the
- Xedge of the map. I used a simple square, flat surface with no "wraparound."
- X
- XI could, and probably will at some point, write a couple of paragraphs about
- Xwhy doing plate movement on a sphere is so hard. All of the methods I
- Xtried required too much data storage for each point, or too much real
- Xnumber computation, or resulted in unacceptable distortion. The criterion
- XI used was to place a small continent, say a 5 x 5 square, anywhere on
- Xthe surface. It should be able to travel one great circle in any direction
- Xand remain undisturbed though the entire journey. The method should not
- Xrequire _any_ floating point computation once the initial velocity is
- Xcomputed since I want to do many iterations on a microcomputer.
- X
- XA second representation issue is how to cause plates to drift apart and
- Xback together. Maintaining the detailed structure of the ocean basin is
- Xcomplicated; consider a circular landmass which splits along a diameter.
- XThe ocean basin structure here is clear, since the rift remains in place and
- Xthe new basin extends out from it in both directions. Now suppose one of
- Xthe semicircular fragments splits in half perpendicular to the first split.
- XThe motion of the landmasses can be computed easily, but the new rift must
- Xdrift as well and the required motions in the basin seem self-contradictory.
- X
- XI chose to ignore the ocean basin and concentrate on the landmasses. Thus,
- Xrifts are not recorded in any way and the ocean floor does not move. Since
- Xthe basins are not simulated, some mechanism is needed to replace the physical
- Xmechanism of the sinking basin sucking the landmasses back together. This
- Xis done by a velocity scaling profile which is coded directly into the
- Xmovement routine. The profile says that after a short time, forward motion
- Xof a landmass slows and then stops; after this point the landmass begins to
- Xmove backwards towards its origin.
- X
- X
- XIII. ALGORITHM
- X
- XThe initial supercontinent is generated by a simple fractal algorithm; a
- Xfractal mountain is created by superimposing four two-dimensional fractal
- Xlines. The mountain is then turned into a binary blob, that is, everything
- Xabove a certain altitude is declared to be land, and everything else becomes
- Xwater. The blob is then "improved" by removing islands and internal oceans.
- XThis technique produces very irregular circular blobs of varying sizes.
- X
- XThe program then repeats a sequence of operations for each timestep. First,
- Xa rift may be generated, splitting some continent into pieces; new velocities
- Xare generated for the new landmasses. Second, the distance each landmass will
- Xmove this timestep is determined by applying the velocity profile described
- Xabove to the landmass velocity. Third, the landmasses are moved and mountains
- Xare built. Fourth, where the movement routine has caused landmasses to
- Xoverlap, new velocities are computed for the overlapping landmasses, and they
- Xmay be merged into a single landmass if they overlap sufficiently. Fifth, the
- Xentire topography is eroded; if a square is higher than the square next to
- Xit, the altitudes are made more equal. Finally, the screen is redrawn.
- X
- XIn step one, random coordinates are generated until a location is found
- Xwhich is at least five squares from any ocean. This location will be the
- Xcenter of a rift, which is represented as a randomly curving line. The
- Xdistance requirement is there to ensure that if a rift occurs, it occurs
- Xon a fairly large continent where internal heat would accumulate. When
- Xthe rift is drawn, it is allowed to bend randomly but is drawn using
- Xconventional digital line-drawing techniques (i.e. Bresenham's algorithm).
- XThe rift drawing routine terminates when the rift hits ocean. If the growing
- Xrift hits another landmass, which could occur if two landmasses were touching
- Xbut had not yet merged, the rift is aborted since the result would be a very
- Xunnatural looking U-shaped continent.
- X
- XOnce the rift is created, a segmentation algorithm determines how
- Xmany new landmasses were formed. There should only be two new landmasses,
- Xbut splinters can be formed if the rift runs along a narrow peninsula or
- Xtoo close to a coast. The algorithm detects and erases such splinters.
- XThe landmasses are given an initial velocity which makes them drift directly
- Xaway from the rift. The velocities are inversely dependent on the area
- Xof the landmass so that smaller masses move faster. After the initial
- Xvelocities have been determined, the rift is erased.
- X
- XThe second and third steps are concerned with moving the landmasses. This
- Xis done with a slightly simpler version of Bresenham's algorithm. The velocity
- Xprofile described in Section II is applied so that landmasses will drift
- Xapart at first, but will then slow down and come back together. Because a
- Xlandmass can split up again, the process does not simply reassemble the
- Xoriginal supercontinent when they drift back together.
- X
- XMountains are built under two conditions: where two landmasses collide, and
- Xwhere landmass subsumes ocean basin. Both conditions are detected and resolved
- Xin the movement routine. Movement is performed from a source array to a
- Xdestination array. A loop steps over every square in the source array. If
- Xthere is land in a square, its new position is computed based on what
- Xlandmass the square belongs to. If there is ocean basin there in the source
- Xarray, the square belongs to the leading edge of a landmass which is subsuming
- Xocean basin. A constant is added to the height of the land in that square.
- XIf there is land there in the destination array, then the two landmasses are
- Xcolliding. There is a collision array which records how many times each
- Xpair of landmasses collide in any given timestep, and the movement routine
- Xincrements the appropriate element of this array for each collision.
- XMountains are built in this case by adding half the height of the lower
- Xterrain to the height of the higher terrain.
- X
- XStep four uses the collision information provided by the movement routine
- Xto adjust the velocities of colliding landmasses and perhaps merge them.
- XFor each pair of colliding landmasses, the routine determines how "strong"
- Xthe collision is this timestep. The velocities are adjusted, again in
- Xinverse proportion to the landmass areas, so that the continents begin
- Xto come to rest with respect to each other. If the relative velocity of
- Xthe two landmasses, after adjustment, is small enough, then the masses
- Xare merged. This is the mechanism that reassembles the continental
- Xfragments into a supercontinent.
- X
- XErosion is the final, and most computation-intensive, step of the simulation.
- XEach pair of adjacent squares is considered exactly once. If either square
- Xis part of a landmass, erosion occurs. Some fraction of the difference between
- Xthe two squares' altitudes is subtracted from the taller and added to the
- Xshorter. This is a very simple algorithm since it ignores many factors,
- Xbut more detail would make the simulation even slower.
- X
- X
- XIV. REFERENCES
- X
- X1. Dole, Stephen H., "Computer Simulation of the Formation of Planetary
- X Systems", Icarus 13 (1970), pp 494-508.
- X2. Hart, Michael H., ""The Evolution of the Atmosphere of the Earth", Icarus
- X 33 (1978), pp 23-39.
- X3. Forrester, J.W., World Dynamics, Wright-Allen Press (1973).
- X4. Wilson, J. Tuzo, "Continental Drift", Scientific American 208, 4 (April
- X 1963), pp 86-100.
- X5. Nance, R.D., Worsley, T.R., and Moody, J.B., "The Supercontinent Cycle",
- X Scientific American (July 1988), pp 72-79.
- END_OF_FILE
- if test 10300 -ne `wc -c <'./doc/about.tec'`; then
- echo shar: \"'./doc/about.tec'\" unpacked with wrong size!
- fi
- # end of './doc/about.tec'
- fi
- if test -f './src/clim.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./src/clim.c'\"
- else
- echo shar: Extracting \"'./src/clim.c'\" \(5481 characters\)
- sed "s/^X//" >'./src/clim.c' <<'END_OF_FILE'
- X/* This program is Copyright (c) 1991 David Allen. It may be freely
- X distributed as long as you leave my name and copyright notice on it.
- X I'd really like your comments and feedback; send e-mail to
- X allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore
- X Avenue, Maynard, MA 01754. */
- X
- X/* This file contains all of the general-purpose routines which are not
- X machine specific: init, mainpar (called by fileio), onestep (called
- X by the machine-specific control routine), and the range-finding
- X function called by several computation routines. */
- X
- X#include "const.h"
- X#include "clim.h"
- X
- X/* L holds the land values everybody starts with; lm is an edge map with
- X continents outlined in black and mountains outlined in white. */
- Xunsigned char l[MAXX][MAXY], lm[MAXX][MAXY];
- X
- X
- X/* These are the parameters used by all of the climate functions. They are
- X described in params.doc. */
- Xint XSIZE = MAXX, YSIZE = MAXY, BSIZE = MAXB;
- Xint PRINTMODE = PRINTMODE_SHORT, MAXRANGE = 15;
- Xint MAXSTEP = 10000, ZCOAST = 0;
- X
- Xint change[] = { 1, 1, 1, 1, 1, 1 }, step = 0;
- Xextern int picktype;
- X
- X
- Xinit (s) char *s; {
- X if (s && *s) getparams (s);
- X fileinit ();
- X heatcomp (); presscomp (); windcomp ();
- X raincomp (); climcomp (); }
- X
- X
- Xonestep () {
- X switch (picktype) {
- X case M_HEAT: heatdraw (step % MAXB); break;
- X case M_PRESS: pressdraw (step % MAXB); break;
- X case M_WIND: windraw (step % MAXB); break;
- X case M_RAIN: raindraw (step % MAXB); break;
- X case M_CLIM: climdraw (); break; } }
- X
- X
- Xmainpar (s) char *s; {
- X /* This function is called by getparams() in fileio.c; it looks at each
- X parameter name read from the input file. If it recognizes the name,
- X the right function is called to set that parameter. The function
- X returns true if it recognizes the parameter name, and false otherwise. */
- X
- X if (CMP ("LAND")) getland ();
- X else if (CMP ("BSIZE")) getlng (&BSIZE, M_MAIN);
- X else if (CMP ("MAXRANGE")) getlng (&MAXRANGE, M_MAIN);
- X else if (CMP ("PRINTMODE")) getlng (&PRINTMODE, M_MAIN);
- X else if (heatpar (s)) { }
- X else if (presspar (s)) { }
- X else if (windpar (s)) { }
- X else if (rainpar (s)) { }
- X else if (climpar (s)) { }
- X else return (0);
- X return (1); }
- X
- X
- Xgetland () { register int i, j, x;
- X /* This function is called by mainpar, above, when the LAND parameter
- X is encountered. It just calls getmat in fileio.c to do the work, but
- X then it also creates an edge map lm; this is used by a couple of the
- X drawing routines as background. */
- X
- X getmat (&XSIZE, &YSIZE, M_MAIN, l);
- X
- X for (j=0; j<YSIZE; j++) for (i=0, x=0; i<XSIZE; i++, x=0) {
- X /* Draw a white line if a mountain is present */
- X if (i) if ((l[i][j] == 2) != (l[i-1][j] == 2)) x |= LINE_1V;
- X if (j) if ((l[i][j] == 2) != (l[i][j-1] == 2)) x |= LINE_1H;
- X
- X /* Draw a black line if a coast is present */
- X if (i) if ((l[i][j] > 0) != (l[i-1][j] > 0)) x |= LINE_0V;
- X if (j) if ((l[i][j] > 0) != (l[i][j-1] > 0)) x |= LINE_0H;
- X
- X /* If both black and white lines are present, white wins */
- X if ((x & LINE_0V) && (x & LINE_1V)) x &= (~LINE_0V);
- X if ((x & LINE_0H) && (x & LINE_1H)) x &= (~LINE_0H);
- X lm[i][j] = x; } }
- X
- X
- Xrange (rr) char rr[MAXX][MAXY]; {
- X /* This function is called by a number of climate routines. It takes an
- X input array with blobs of -1's on a background of 0's. The function winds
- X up replacing each 0 with the distance from that square to the nearest -1.
- X The function onerange() does all the work, but it will not compute ranges
- X greater than MAXRANGE. Therefore, after onerange() is called, any remaining
- X 0 values must be replaced with MAXRANGE, indicating that that square is
- X "very far" from any -1 value. */
- X
- X register int i, j;
- X
- X onerange (rr); checkmouse ();
- X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++)
- X if (!rr[i][j]) rr[i][j] = MAXRANGE; }
- X
- X
- Xonerange (rr) char rr[MAXX][MAXY]; {
- X /* This routine consists of a loop. Each time through the loop, every
- X square is checked. If the square is zero, it has not yet been updated.
- X In that case, look to see if any adjacent squares were previously updated
- X (or if they were initialized to -1). If so, set the square to the current
- X distance value, which happens to be identical to the outer loop variable.
- X If, after one loop iteration, no squares have been updated, the matrix
- X must be completely updated. Stop. To keep down run-time, a maximum
- X distance value, MAXRANGE, is used as the terminating loop value. */
- X
- X register int i, j, x, k, keepgo;
- X for (k=1; k<MAXRANGE; k++) {
- X checkmouse ();
- X for (keepgo=0, j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++)
- X if (!rr[i][j]) {
- X keepgo = 1;
- X x = rr[i ? i-1 : XSIZE-1][j]; if (x && (x != k)) rr[i][j] = k;
- X x = rr[(i<XSIZE-1) ? i+1 : 0][j]; if (x && (x != k)) rr[i][j] = k;
- X if (j<YSIZE-1) { x = rr[i][j+1]; if (x && (x != k)) rr[i][j] = k; }
- X if (j) { x = rr[i][j-1]; if (x && (x != k)) rr[i][j] = k; } }
- X if (!keepgo) return (0); } return (0); }
- X
- X
- Xstatus (n, i) int n, i; {
- X static char *title[] = { "", "Heat","Pressure","Wind","Rain","Climate" };
- X char t[256];
- X sprintf (t, "%s buffer %d", title[n], i); usermessage (t); }
- X
- X
- Xdouble greyscale (x) int x; {
- X /* This function just returns the 0..1 equivalent of 0..255 */
- X return ((float) ((255 - x) / 320.0) + 0.1); }
- END_OF_FILE
- if test 5481 -ne `wc -c <'./src/clim.c'`; then
- echo shar: \"'./src/clim.c'\" unpacked with wrong size!
- fi
- # end of './src/clim.c'
- fi
- if test -f './src/heat.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./src/heat.c'\"
- else
- echo shar: Extracting \"'./src/heat.c'\" \(6893 characters\)
- sed "s/^X//" >'./src/heat.c' <<'END_OF_FILE'
- X/* This program is Copyright (c) 1991 David Allen. It may be freely
- X distributed as long as you leave my name and copyright notice on it.
- X I'd really like your comments and feedback; send e-mail to
- X allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore
- X Avenue, Maynard, MA 01754. */
- X
- X/* This file contains the routines that compute local temperatures */
- X
- X#include "const.h"
- X#include "clim.h"
- X
- X/* Some private defines. FREEZING is 0 degrees C in Kelvin; DEG2RAD is the
- X conversion factor from angular degrees to radians. */
- X
- X#define FREEZING 273.0
- X#define PI 3.14159
- X#define DEG2RAD (PI / 180)
- X
- X/* The input array is l, from main.c; lm is used by heatdraw(). The output
- X array is ts, containing temperatures. Array t is an unscaled copy of the
- X temperatures; tmin and tmax are used for scaling, and tscale is the
- X computed scale factor. To convert the unscaled temperatures to degrees K,
- X divide by TEMPSCALE. */
- X
- Xextern unsigned char l[MAXX][MAXY], lm[MAXX][MAXY];
- Xunsigned char ts[MAXB][MAXX][MAXY];
- Xint tt[MAXB][MAXX][MAXY], tmax, tmin;
- Xdouble tscale; int TEMPSCALE = 10;
- X
- X/* These parameters are defined in main.c */
- X
- Xextern int BSIZE, XSIZE, YSIZE, PRINTMODE;
- X
- X/* These parameters are used here, and are described in params.doc */
- X
- Xint PRINTEMP = 0;
- Xdouble TILT = 23.0, ECCENT = 0.0, ECCPHASE = 0.0;
- Xdouble LCOS = 45.0, LCONST = 275.0, LTILT = 1.0, LSMOOTH = 0.6, LDIV = 180.0;
- Xdouble OCOS = 30.0, OCONST = 275.0, OTILT = 0.2, OSMOOTH = 0.2, ODIV = 250.0;
- X
- X
- Xheatpar (s) char *s; {
- X /* This function is called by mainpar() in main.c; it simply tests input
- X parameter names to see if they are defined in this file. Each of the
- X above ints are defined in this file. If the input string matches here,
- X the function returns true. */
- X if (CMP ("TILT")) getdbl (&TILT, M_HEAT);
- X else if (CMP ("ECCENT")) getdbl (&ECCENT, M_HEAT);
- X else if (CMP ("ECCPHASE")) getdbl (&ECCPHASE, M_HEAT);
- X
- X else if (CMP ("LCOS")) getdbl (&LCOS, M_HEAT);
- X else if (CMP ("LCONST")) getdbl (&LCONST, M_HEAT);
- X else if (CMP ("LTILT")) getdbl (<ILT, M_HEAT);
- X else if (CMP ("LSMOOTH")) getdbl (&LSMOOTH, M_HEAT);
- X else if (CMP ("LDIV")) getdbl (&LDIV, M_HEAT);
- X
- X else if (CMP ("OCOS")) getdbl (&OCOS, M_HEAT);
- X else if (CMP ("OCONST")) getdbl (&OCONST, M_HEAT);
- X else if (CMP ("OTILT")) getdbl (&OTILT, M_HEAT);
- X else if (CMP ("OSMOOTH")) getdbl (&OSMOOTH, M_HEAT);
- X else if (CMP ("ODIV")) getdbl (&ODIV, M_HEAT);
- X
- X else if (CMP ("PRINTEMP")) getlng (&PRINTEMP, M_HEAT);
- X else return (0);
- X return (1); }
- X
- X
- Xheatlut (x, s) int x; char *s; {
- X /* After the heatcomp routine is finished, a scale factor is computed
- X for converting degrees K to 0..255; this routine converts back. Functions
- X in the machine-dependent code can call here to print map keys. The caller
- X must provide a char buffer; a string containing degrees F is put there. */
- X
- X double temp;
- X
- X temp = (((double) x / tscale) + (double) tmin) / TEMPSCALE;
- X temp = (temp - FREEZING) * 1.8 + 32;
- X sprintf (s, "%6.1f", temp); }
- X
- X
- Xheatcomp () {
- X /* This is the main routine for computing temperatures. After getheat()
- X is called to do all the work, this routine takes the ints from t and
- X finds the smallest and largest values. These are used to compute a scale
- X factor, tscale; the arrays ts are then filled with scaled values. Finally,
- X putmat() from main.c is called if needed to print results. */
- X
- X register int i, j, buf; char s[20];
- X
- X getheat (); tmin = 32000; tmax = 0;
- X
- X usermessage ("Scaling heat");
- X /* Find minimum and maximum across all buffers */
- X for (buf=0; buf<BSIZE; buf++) {
- X checkmouse ();
- X for (i=0; i<XSIZE; i++) for (j=0; j<YSIZE; j++) {
- X if (tt[buf][i][j] < tmin) tmin = tt[buf][i][j];
- X if (tt[buf][i][j] > tmax) tmax = tt[buf][i][j]; } }
- X
- X /* Compute scale; for every buffer, fill ts from t */
- X tscale = 254.0 / ((double) (tmax - tmin));
- X for (buf=0; buf<BSIZE; buf++) {
- X for (i=0; i<XSIZE; i++) for (j=0; j<YSIZE; j++)
- X ts[buf][i][j] = (tt[buf][i][j] - tmin) * tscale;
- X checkmouse (); }
- X
- X if (PRINTEMP) {
- X if (PRINTMODE != PRINTMODE_GREY) {
- X printf ("(KEY-IN-FAREN (\n");
- X for (i=0; i<8; i++) { heatlut (16 * i, s); printf (" %s", s); }
- X printf ("\n");
- X for (i=8; i<16; i++) { heatlut (16 * i, s); printf (" %s", s); }
- X printf ("))\n"); }
- X for (i=0; i<BSIZE; i++)
- X putmat ("TEMPERATURE", i, PRINTMODE_SCALE, ts[i], lm); } }
- X
- X
- Xheatdraw (n) int n; { draw (DRAW_GREY, LINE_CORN, ts[n], lm); }
- X /* This function calls draw() with the right arguments to display heat */
- X
- X
- Xgetheat () {
- X /* This function does all the work for computing temperatures. The outermost
- X loop goes through each row of the output array once, computing all buffers
- X at the same time. The loop has two inner loops: first, tland and tsea are
- X filled with the temperatures found far inland and far at sea for each buffer.
- X In the second loop, the weight function for each point in the latitude line
- X is computed and the temperature is found for each buffer. */
- X
- X register int buf, i, j;
- X double lat, lscl, sscl, x, fact, theta, delth, phase;
- X double tland[MAXB], tsea[MAXB];
- X
- X lscl = DEG2RAD * 180.0 / (90.0 + LTILT * TILT);
- X sscl = DEG2RAD * 180.0 / (90.0 + OTILT * TILT);
- X delth = 2.0 * PI / (double) BSIZE;
- X for (j=0; j<YSIZE; j++) {
- X status (M_HEAT, j); checkmouse ();
- X lat = 90.0 - 180.0 * (double) j / (double) YSIZE;
- X for (buf=0, theta=0; buf<BSIZE; buf++, theta+=delth) {
- X phase = theta + ECCPHASE; if (phase > 2.0 * PI) phase -= (2 * PI);
- X fact = (1.0 + ECCENT * cos (phase)) * TEMPSCALE;
- X x = (lat + cos (theta) * TILT * LTILT) * lscl;
- X tland[buf] = (LCONST + LCOS * cos (x)) * fact;
- X x = (lat + cos (theta) * TILT * OTILT) * sscl;
- X tsea[buf] = (OCONST + OCOS * cos (x)) * fact; }
- X for (i=0; i<XSIZE; i++) {
- X if (!l[i][j]) x = OSMOOTH + (countland (i, j) / ODIV);
- X else x = LSMOOTH + (countland (i, j) / LDIV);
- X for (buf=0; buf<BSIZE; buf++)
- X tt[buf][i][j] = tsea[buf] + (tland[buf] - tsea[buf]) * x; } } }
- X
- X
- Xcountland (x, y) int x, y; {
- X /* Called by getheat() for each square, this function looks in a 11 wide
- X by 5 high box and counts the number of land squares found there. It
- X compensates for y values off the map, and wraps x values around. The
- X answer is returned. */
- X
- X register int sum=0; int jmin, jmax, j1, i0, i1;
- X
- X jmin = y - 2; if (jmin < 0) jmin = 0;
- X jmax = y + 2; if (jmax >= YSIZE) jmax = YSIZE-1;
- X for (j1=jmin; j1<=jmax; j1++) for (i0=-5; i0<6; i0++) {
- X i1 = i0 + x; if (i1 < 0) i1 += XSIZE;
- X if (i1 >= XSIZE) i1 -= XSIZE;
- X sum += l[i1][j1]; }
- X return (sum); }
- END_OF_FILE
- if test 6893 -ne `wc -c <'./src/heat.c'`; then
- echo shar: \"'./src/heat.c'\" unpacked with wrong size!
- fi
- # end of './src/heat.c'
- fi
- if test -f './src/pressure.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./src/pressure.c'\"
- else
- echo shar: Extracting \"'./src/pressure.c'\" \(9001 characters\)
- sed "s/^X//" >'./src/pressure.c' <<'END_OF_FILE'
- X/* This program is Copyright (c) 1991 David Allen. It may be freely
- X distributed as long as you leave my name and copyright notice on it.
- X I'd really like your comments and feedback; send e-mail to
- X allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore
- X Avenue, Maynard, MA 01754. */
- X
- X/* This file contains the routines to compute global high and low
- X pressure areas. */
- X
- X#include "const.h"
- X#include "clim.h"
- X
- X/* These are the data arrays required: l is an input array defining the
- X ocean, land and mountain areas; ts is the temperature array computed
- X by the functions in heat.c. Array pr is filled by ocean(), land() and
- X heateq(), below; PR_HIGH indicates a high pressure zone, PR_LOW indicates
- X a low, and PR_HEQ indicates the heat equator, a low zone. Array pm is
- X the output array for this file, and it contains an edge map which has
- X edges in color 1 surrounding lows and color 0 around highs. Array r is
- X temporary storage for local calls to range() in main.c. */
- X
- Xextern unsigned char l[MAXX][MAXY], ts[MAXB][MAXX][MAXY];
- Xstatic char r[MAXX][MAXY];
- Xstatic unsigned char pm[MAXB][MAXX][MAXY];
- Xunsigned char pr[MAXB][MAXX][MAXY];
- X
- X
- X/* The externs below are declared in main.c; they represent global parameters.
- X The ints are described in params.doc. */
- X
- Xextern int BSIZE, XSIZE, YSIZE, PRINTMODE;
- Xint OOTHRESH = 5, OLTHRESH = 1, LOTHRESH = 3, LLTHRESH = 7;
- Xint OHMIN = 130, OHMAX = 180, OLMIN = 40, OLMAX = 65;
- Xint LHMIN = 0, LHMAX = 20, LLMIN = 220, LLMAX = 255;
- Xint PRINTPR = 0;
- X
- X
- Xpresspar (s) char *s; {
- X /* This function is called by mainpar() in main.c; it simply tests input
- X parameters to see if they are defined in this file. Each of the above
- X ints is referred to in this function. If an input string matches here,
- X the function returns true. */
- X if (CMP ("OOTHRESH")) getlng (&OOTHRESH, M_PRESS);
- X else if (CMP ("OLTHRESH")) getlng (&OLTHRESH, M_PRESS);
- X else if (CMP ("OHMIN")) getlng (&OHMIN, M_PRESS);
- X else if (CMP ("OHMAX")) getlng (&OHMAX, M_PRESS);
- X else if (CMP ("OLMIN")) getlng (&OLMIN, M_PRESS);
- X else if (CMP ("OLMAX")) getlng (&OLMAX, M_PRESS);
- X
- X else if (CMP ("LOTHRESH")) getlng (&LOTHRESH, M_PRESS);
- X else if (CMP ("LLTHRESH")) getlng (&LLTHRESH, M_PRESS);
- X else if (CMP ("LHMIN")) getlng (&LHMIN, M_PRESS);
- X else if (CMP ("LHMAX")) getlng (&LHMAX, M_PRESS);
- X else if (CMP ("LLMIN")) getlng (&LLMIN, M_PRESS);
- X else if (CMP ("LLMAX")) getlng (&LLMAX, M_PRESS);
- X
- X else if (CMP ("PRINTPR")) getlng (&PRINTPR, M_PRESS);
- X else return (0);
- X return (1); }
- X
- X
- Xpresscomp () {
- X /* The main routine for this file. It just calls the four routines
- X which do all the work. Ocean() finds pressure extremes on the ocean;
- X land() does the same for land; heateq() defines the heat equator, and
- X setpm() computes pm[][] from pr[][]. */
- X
- X int buf;
- X
- X for (buf=0; buf<BSIZE; buf++) {
- X status (M_PRESS, buf); ocean (buf); land (buf);
- X checkmouse (); findheq (buf); setpm (buf); }
- X if (PRINTPR) for (buf=0; buf<BSIZE; buf++) {
- X if (PRINTMODE == PRINTMODE_GREY)
- X putmat ("PRESSURE", buf, PRINTMODE_SHORT, l, pm[buf]);
- X else putmat ("PRESSURE", buf, PRINTMODE_SHORT, pr[buf], 0); } }
- X
- X
- Xpressdraw (n) int n; { draw (DRAW_LAND, LINE_CORN, l, pm[n]); }
- X /* This function calls draw with the right arguments to display pressure */
- X
- X
- Xocean (buf) int buf; {
- X /* Determine ocean highs and lows. An ocean high or low must occur over
- X ocean, far away from major land masses. Two calls to range() are made
- X to find the qualifying ocean areas; then temperature criteria are used
- X to select the actual pressure zones. */
- X
- X register int i, j; int x;
- X
- X /* Set r to the distance on land from the coast. */
- X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++) r[i][j] = l[i][j] ? 0 : -1;
- X range (r);
- X
- X /* Initialize r to contain blobs on land which are at least OLTHRESH squares
- X away from the coast. Then set r to the distance from these. The result
- X in r is the distance from the nearest big piece of land (ignoring
- X islands). */
- X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++)
- X r[i][j] = (r[i][j] > OLTHRESH) ? -1 : 0;
- X range (r);
- X
- X /* For each array element, if it is at least OOTHRESH squares from the
- X nearest big piece of land, it might be the center of an ocean pressure
- X zone. The pressure zones are defined by temperature ranges; if the
- X temperature in ts is between OLMIN and OLMAX, a low is recorded, while
- X if the temperature is between OHMIN and OHMAX, a high is recorded. */
- X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++) {
- X pr[buf][i][j] = 0; x = ts[buf][i][j];
- X if (r[i][j] > OOTHRESH) {
- X if ((x >= OLMIN) && (x <= OLMAX)) pr[buf][i][j] = PR_LOW;
- X if ((x >= OHMIN) && (x <= OHMAX)) pr[buf][i][j] = PR_HIGH; } } }
- X
- X
- Xland (buf) int buf; {
- X /* This function is simply the complement of ocean(): it finds land highs
- X and lows. A land high or low must occur over land, far from major oceans.
- X Two calls to range() are made to find the qualifying land areas; then
- X temperature criteria are used to select the actual pressure zones. */
- X
- X register int i, j; int x;
- X
- X /* Set r to distance on water from coast. */
- X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++) r[i][j] = l[i][j] ? -1 : 0;
- X range (r);
- X
- X /* Initialize r to contain blobs on ocean which are at least LOTHRESH
- X squares away from the coast. Then set r to the distance from these. The
- X result in r is the distance from the nearest ocean, ignoring lakes. */
- X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++)
- X r[i][j] = (r[i][j] > LOTHRESH) ? -1 : 0;
- X range (r);
- X
- X /* For each array element, if it is at least LLTHRESH squares from the
- X nearest large ocean, it might be the center of a land pressure zone.
- X The pressure zones are defined by temperature ranges; if the temperature
- X in ts is between LLMIN and LLMAX, a low is recorded, while if the
- X temperature is between LHMIN and LHMAX, a high is recorded. */
- X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++) {
- X x = ts[buf][i][j];
- X if (r[i][j] > LLTHRESH) {
- X if ((x >= LLMIN) && (x <= LLMAX)) pr[buf][i][j] = PR_LOW;
- X if ((x >= LHMIN) && (x <= LHMAX)) pr[buf][i][j] = PR_HIGH; } } }
- X
- X
- Xfindheq (buf) int buf; {
- X /* This function finds the heat equator and marks it in pr. For each
- X vertical column of ts, the median position is found and marked. To
- X make the heat equator continuous, jlast is set to the position of the
- X heat equator in the previous column; a connection is made in the present
- X column to ensure continuity. */
- X
- X register int i, j; int sum, jlast = 0, jnext;
- X
- X for (i=0; i<XSIZE; i++) {
- X /* Find the total of the temperatures in this column */
- X for (sum=0, j=0; j<YSIZE; j++) sum += ts[buf][i][j];
- X
- X /* Step through the column again until the total so far is exactly
- X half the total for the column. This is the median position. */
- X for (sum>>=1, j=0; j<YSIZE && sum>0; j++) sum -= ts[buf][i][j];
- X
- X /* Mark this position and remember it with jnext */
- X pr[buf][i][j] = PR_HEQ; jnext = j;
- X
- X /* For each column except the first (where i = 0), if the last heat
- X equator is above this one, move upwards to it, marking each square,
- X to ensure continuity; if below this one, move downwards to it. */
- X
- X if (i && (j > jlast)) for (; j>=jlast; j--) pr[buf][i][j] = PR_HEQ;
- X else if (i && (j < jlast)) for (; j<=jlast; j++) pr[buf][i][j] = PR_HEQ;
- X
- X /* Remember this position for the next column. Note that no check is
- X done to ensure continuity at the wraparound point; this is bad. */
- X jlast = jnext; } }
- X
- X
- Xsetpm (buf) int buf; {
- X /* Setpm() is called after the above three functions have filled pr with
- X the codes for high, low and heat equator. The purpose of this function
- X is to create an edge map surrounding lows with color 1 and highs with
- X color 0. */
- X
- X register int i, j, k; int col;
- X
- X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++) {
- X k = pr[buf][i][j]; col = 0;
- X
- X /* If not at the top edge, and if the pressure status here is not equal
- X to the pressure status one square up, then put a horizontal line in
- X this square. The color is zero if there is a high here; if a low or
- X heat equator (a type of low) is here, the color is one. */
- X if (j) if (k != pr[buf][i][j-1]) col =
- X ((k == PR_HIGH) || (pr[buf][i][j-1] == PR_HIGH)) ? LINE_0H : LINE_1H;
- X /* Similarly, if not at the left edge, put a vertical line in the right
- X color. Notice that this color is OR'ed with the previous color. */
- X if (i) if (k != pr[buf][i-1][j]) col |=
- X ((k == PR_HIGH) || (pr[buf][i-1][j] == PR_HIGH)) ? LINE_0V : LINE_1V;
- X
- X /* Set the square in the pm array to the resultant color */
- X pm[buf][i][j] = col; } }
- X
- END_OF_FILE
- if test 9001 -ne `wc -c <'./src/pressure.c'`; then
- echo shar: \"'./src/pressure.c'\" unpacked with wrong size!
- fi
- # end of './src/pressure.c'
- fi
- if test -f './src/tec1.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./src/tec1.c'\"
- else
- echo shar: Extracting \"'./src/tec1.c'\" \(10750 characters\)
- sed "s/^X//" >'./src/tec1.c' <<'END_OF_FILE'
- X/* This program is Copyright (c) 1991 David Allen. It may be freely
- X distributed as long as you leave my name and copyright notice on it.
- X I'd really like your comments and feedback; send e-mail to
- X allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore Ave,
- X Maynard, MA 01754. */
- X
- X/* This is the file containing all of the important functions except for
- X trysplit (), which splits a continent into pieces. Also, all of the main
- X arrays are declared here, even a couple that are only used by functions in
- X tec2.c. The array declarations are first, followed by the sequencing
- X function onestep () and some miscellaneous routines including the text
- X output routines; initialization routines and the routines that do all
- X the interesting stuff are last. */
- X
- X#include "const.h"
- X#include "tec.h"
- X
- X/* These are the parameters and their default values; each is defined in
- X params.doc */
- Xint XSIZE = 100, YSIZE = 100, MAXSTEP = 100;
- Xint MAXBUMP = 50, BUMPTOL = 50, UNDERSCAN = 0;
- Xint HYDROPCT = 70, DRAWEVERY = 0, PRINTMODE = PRINTMODE_NONE;
- Xint ZINIT = 22, ZSUBSUME = 16, ZCOAST = 16;
- Xint ZSHELF = 8, ZMOUNTAIN = 48, ZERODE = 16;
- Xint RIFTPCT = 40, DOERODE = 1, ERODERND = 4;
- Xint MAXCTRTRY = 50, RIFTDIST = 5, BENDEVERY = 6;
- Xint BENDBY = 50, SPEEDRNG = 300, SPEEDBASE = 200;
- X
- Xdouble MR [] = { 1.0,1.0,1.0,0.7,0.4,0.1,-0.2,-0.5,-0.8,-1.0 };
- Xint MAXLIFE = 10; /* Length of MR vector */
- Xint change[1]; /* needed for fileio */
- X
- X/* The following arrays are global and most are used by functions in both
- X source files. The two main ones are m and t. Each is set up to be two
- X 2-d arrays, where each array is the size of the whole world. M is the
- X map; elements in m are indices of plates, showing which squares are
- X covered by which plate. T is the topography; elements in t are altitudes. */
- X
- Xchar m[2][MAXX][MAXY]; unsigned char t[2][MAXX][MAXY];
- X
- X/* Several arrays are used by the binary blob segmenter, segment() in tec2.c.
- X These include r, which is used to store fragment indices; many fragments
- X make up one region during a segmentation. Kid is a lookup table; fragment
- X k belongs to region kid[k] after a segmentation is finished. Karea[k]
- X is the area of fragment k. */
- X
- Xchar r[MAXX][MAXY], kid[MAXFRAG]; int karea [MAXFRAG];
- X
- X/* The merge routine gets information from the move routine; when the move
- X routine puts a square of one plate on top of another plate, that information
- X is recorded in the merge matrix mm. */
- X
- Xchar mm[MAXPLATE][MAXPLATE];
- X
- X/* The erosion routine needs an array to store delta information; during an
- X erosion, the increases or decreases in elevation are summed in e and then
- X applied all at once to the topography. */
- X
- Xchar e[MAXX][MAXY];
- X
- X/* Several routines need temporary storage for areas and plate identifiers. */
- X
- Xint tarea[MAXPLATE]; int ids[MAXPLATE];
- X
- X/* The plates in use are stored in this data structure. Dx,dy are the
- X values to move by THIS STEP ONLY; odx,ody are the permanent move
- X values; rx,ry are the remainder x and y values used by newdxy() to
- X determine dx,dy; age is the age of the plate, in steps; area is the
- X area of the plate, in squares; id is the value in the m array which
- X corresponds to this plate; next is a pointer to the next occupied
- X element of the plate array. */
- X
- Xstruct plate p [MAXPLATE];
- X
- X/* The linked list header for available plates and used plates are global,
- X as is the step counter. */
- X
- Xint pavail, phead, step;
- X
- X
- Xonestep () {
- X /* This is the sequencing routine called by main once per step.
- X It just calls the important subfunctions in order:
- X - trysplit finds a plate to break up, and computes new velocities
- X - newdxy computes the deltas to move each plate this step
- X - move moves the plates
- X - merge determines results when plates rub together
- X - erode erodes the terrain, adding or subtracting altitude
- X - draw draw the resulting array once every DRAWEVERY steps
- X The m and t arrays are double-buffered in the sense that operations go
- X from m[0] to m[1] or vice-versa; src and dest determine which is which. */
- X
- X int src, dest;
- X
- X src = step % 2; dest = 1 - src;
- X if (rnd (100) < RIFTPCT) trysplit (src);
- X newdxy ();
- X move (src, dest);
- X merge (dest);
- X if (DOERODE) erode (dest);
- X draw (DRAW_TEC, LINE_NONE, t[dest], 0);
- X
- X if (DRAWEVERY) if (step && !(step % DRAWEVERY)) tecst (dest);
- X if (!DRAWEVERY && (step == MAXSTEP - 1)) tecst (dest); }
- X
- X
- Xpalloc () {
- X /* Allocate a plate from the array and return its index. All the fields
- X of the plate are initialized to 0, except `next'. That field is used to
- X link together the plate structures in use. */
- X
- X int x;
- X
- X if (!pavail) panic ("No more objects");
- X x = pavail; pavail = p[x].next;
- X p[x].next = phead; phead = x;
- X p[x].area = 0; p[x].age = 0;
- X p[x].rx = 0; p[x].ry = 0;
- X p[x].odx = 0; p[x].ody = 0;
- X p[x].dx = 0; p[x].dy = 0;
- X return (x); }
- X
- X
- Xpfree (n) int n; {
- X /* Return a plate array element to the pool of available elements.
- X To check for infinite loops, the variable guard is incremented
- X at each operation; if the number of operations exceeds the maximum
- X possible number, the program panics. */
- X
- X int i, guard = 0;
- X
- X if (phead == n) phead = p[n].next;
- X else {
- X for (i=phead; p[i].next!=n; i=p[i].next)
- X if (++guard > MAXPLATE) panic ("Infinite loop in pfree");
- X p[i].next = p[n].next; }
- X p[n].next = pavail; pavail = n; }
- X
- X
- Xmainpar (s) char *s; {
- X if (CMP ("XSIZE")) getdim (&XSIZE, 0);
- X else if (CMP ("YSIZE")) getdim (&YSIZE, 0);
- X else if (CMP ("MOVERATE")) getdvec (&MAXLIFE, MR, 0);
- X else if (CMP ("MAXSTEP")) getlng (&MAXSTEP, 0);
- X else if (CMP ("MAXBUMP")) getlng (&MAXBUMP, 0);
- X else if (CMP ("BUMPTOL")) getlng (&BUMPTOL, 0);
- X else if (CMP ("DRAWEVERY")) getlng (&DRAWEVERY, 0);
- X else if (CMP ("PRINTMODE")) getlng (&PRINTMODE, 0);
- X else if (CMP ("HYDROPCT")) getlng (&HYDROPCT, 0);
- X else if (CMP ("ZINIT")) getlng (&ZINIT, 0);
- X else if (CMP ("ZSUBSUME")) getlng (&ZSUBSUME, 0);
- X else if (CMP ("ZCOAST")) getlng (&ZCOAST, 0);
- X else if (CMP ("ZSHELF")) getlng (&ZSHELF, 0);
- X else if (CMP ("ZMOUNTAIN")) getlng (&ZMOUNTAIN, 0);
- X else if (CMP ("ZERODE")) getlng (&ZERODE, 0);
- X else if (CMP ("RIFTPCT")) getlng (&RIFTPCT, 0);
- X else if (CMP ("DOERODE")) getlng (&DOERODE, 0);
- X else if (CMP ("ERODERND")) getlng (&ERODERND, 0);
- X else if (CMP ("MAXCTRTRY")) getlng (&MAXCTRTRY, 0);
- X else if (CMP ("RIFTDIST")) getlng (&RIFTDIST, 0);
- X else if (CMP ("BENDEVERY")) getlng (&BENDEVERY, 0);
- X else if (CMP ("BENDBY")) getlng (&BENDBY, 0);
- X else if (CMP ("SPEEDBASE")) getlng (&SPEEDBASE, 0);
- X else if (CMP ("SPEEDRNG")) getlng (&SPEEDRNG, 0);
- X else if (CMP ("UNDERSCAN")) getlng (&UNDERSCAN, 0);
- X else return (0);
- X return (1); }
- X
- X
- Xtecst (src) int src; {
- X /* This function is called whenever map output is called for. It looks
- X at the parameter `printmode' to decide between long text, simple text,
- X and PostScript output formats. Note that the default for this
- X function is no output at all, corresponding to PRINTMODE_NONE. If only
- X one output map is desired, then move the coastline up or down to meet the
- X desired hydrographic percentage. */
- X
- X register int i, j, zcoast; int hist[256], goal; unsigned char sk[MAXX][MAXY];
- X
- X if (!PRINTMODE) return (0);
- X if (!DRAWEVERY) {
- X /* Create a histogram of the output array */
- X for (i=0; i<256; i++) hist[i] = 0;
- X for (i=0; i<XSIZE; i++)
- X for (j=0; j<YSIZE; j++) hist[t[src][i][j]]++;
- X
- X /* Starting from the highest altitude, move down until number of */
- X /* squares above water is slightly greater than the exact goal */
- X goal = XSIZE * YSIZE;
- X goal = (goal * (100 - HYDROPCT)) / 100;
- X for (zcoast=255, i=0; zcoast>0; zcoast--)
- X if ((i += hist[zcoast]) > goal) break;
- X
- X /* If the new coast level is zero, then there wasn't enough land */
- X /* to meet the goal, even going right down to the ocean floor. The */
- X /* only possible result is to panic since the goal can't be met. */
- X if (!zcoast) panic ("Scaled till oceans dried up");
- X ZCOAST = zcoast; }
- X
- X if (PRINTMODE != PRINTMODE_SHORT) putmat ("LAND", -1, PRINTMODE, t[src], 0);
- X else {
- X for (i=0; i<XSIZE; i++) for (j=0; j<YSIZE; j++) {
- X if (t[src][i][j] < ZCOAST) sk[i][j] = 0;
- X else if (t[src][i][j] > ZMOUNTAIN) sk[i][j] = 2;
- X else sk[i][j] = 1; }
- X putmat ("LAND", -1, PRINTMODE, sk, 0); }
- X return (0); }
- X
- X
- Xdouble greyscale (x) int x; {
- X /* Called by the PostScript print routine, this function simply computes
- X the intensity from 0-1 corresponding to the altitude 0-255 */
- X if (x < ZCOAST) return ((float) 0);
- X return (1.0 - ((x > 128) ? 128 : x) / 128.0); }
- X
- X
- Xinit (s) char *s; {
- X /* This is the catchall function that initializes everything. First,
- X it calls getparams() in fileio.c to allow the user to set parameters. Next,
- X it links together the plates onto the free list and starts the used list
- X at empty. The first plate is created by a fractal technique and then
- X improved. Finally, the fractal is copied to the data array and drawn.
- X There are two kinds of improvement done here. First, islands are
- X eliminated by segmenting the blob and erasing all the regions except
- X for the biggest. Second, oceans inside the blob (holes) are eliminated
- X by segmenting the _ocean_ and filling in all regions except the biggest. */
- X
- X int besti, x; register int i, j;
- X
- X if (s) if (*s) getparams (s); fileinit ();
- X
- X for (i=1; i<MAXPLATE; i++) p[i].next = i + 1;
- X p[MAXPLATE-1].next = 0;
- X pavail = 1; phead = 0;
- X
- X /* Allocate a plate structure for the first plate and make a blob */
- X x = palloc (); makefrac (0, x);
- X
- X /* Segment m[0] looking for x, set besti to the largest region, */
- X /* and zero out all the other regions. This eliminates islands. */
- X besti = singlefy (0, x);
- X if (besti > 0) for (i=1; i<XSIZE; i++) for (j=1; j<YSIZE; j++)
- X if (kid[r[i][j]] != besti) m[0][i][j] = 0;
- X
- X /* Segment m[0] looking for 0 (ocean), set besti to the largest region, */
- X /* and fill in all the other regions. This eliminates holes in the blob. */
- X besti = singlefy (0, 0);
- X if (besti > 0) for (i=1; i<XSIZE; i++) for (j=1; j<YSIZE; j++)
- X if (kid[r[i][j]] != besti) m[0][i][j] = x;
- X
- X /* Fill the topo structure with the blob shape while finding its area */
- X for (i=0; i<XSIZE; i++) for (j=0; j<YSIZE; j++)
- X if (m[0][i][j]) { t[0][i][j] = ZINIT; p[x].area++; }
- X
- X /* Draw the blob */
- X if (DRAWEVERY) draw (DRAW_TEC, LINE_NONE, t[0], 0); }
- END_OF_FILE
- if test 10750 -ne `wc -c <'./src/tec1.c'`; then
- echo shar: \"'./src/tec1.c'\" unpacked with wrong size!
- fi
- # end of './src/tec1.c'
- fi
- if test -f './src/x.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./src/x.c'\"
- else
- echo shar: Extracting \"'./src/x.c'\" \(7119 characters\)
- sed "s/^X//" >'./src/x.c' <<'END_OF_FILE'
- X/* This program is Copyright (c) 1991 David Allen. It may be freely
- X distributed as long as you leave my name and copyright notice on it.
- X I'd really like your comments and feedback; send e-mail to
- X allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore Ave,
- X Maynard, MA 01754.
- X
- X Based on code written by by George Ferguson (ferguson@cs.rochester.edu),
- X 28 Apr 1990. That code was intended for an X version of "tec", never
- X released. */
- X
- X#include <math.h>
- X#include <X11/StringDefs.h>
- X#include <X11/Intrinsic.h>
- X#include <X11/keysym.h>
- X#include <X11/Xaw/Box.h>
- X#include <X11/Xaw/Command.h>
- X#include <X11/Xaw/Viewport.h>
- X#include <X11/Shell.h>
- X#include "const.h"
- X#include "clim.h"
- X
- X#define SIZE 6
- X#define WINDOW_HEIGHT (SIZE*MAXX)
- X#define WINDOW_WIDTH (SIZE*MAXY)
- X
- Xextern int MAXSTEP, XSIZE, YSIZE, step;
- Xint picktype = M_HEAT;
- X
- Xstatic XtAppContext appc;
- Xstatic Display *Dis;
- Xstatic Window Win;
- Xstatic Pixmap Pix;
- Xstatic Pixmap Pixsave;
- Xstatic GC gc_def;
- Xstatic GC Gc[32];
- X
- X
- Xstatic Arg simple_args[] = {
- X {XtNfromVert, (XtArgVal) NULL},
- X {XtNheight, (XtArgVal) WINDOW_HEIGHT},
- X {XtNwidth, (XtArgVal) WINDOW_WIDTH} };
- X
- X
- Xunsigned char landcols [] = { 11, 28, 3 }, greycols[256], tecols[256];
- Xunsigned char climcols [] = { 9, 20, 18, 2, 3, 18, 22, 26, 14, 17, 12 };
- Xstatic char *color_names[] = {
- X "black","white","grey75", "grey50",
- X "MediumPurple1","purple4","purple3","purple2","purple1",
- X "blue4","blue3","blue2","blue1",
- X "DarkGreen","green4","green3","green2","green1",
- X "DarkGoldenrod4","yellow4","yellow3","yellow2","yellow1",
- X "orange4","orange3","orange2","orange1",
- X "brown4","red4","red3","red2","red1" };
- X
- X
- Xmain (argc,argv) int argc; char **argv; {
- X Widget toplevel, top_form, surface;
- X XWindowAttributes wattr; ushort seed16v[3];
- X
- X XtToolkitInitialize ();
- X appc = XtCreateApplicationContext ();
- X
- X Dis = XtOpenDisplay (appc, NULL, NULL, "Demo", NULL, 0, &argc, argv);
- X toplevel = XtAppCreateShell (NULL, NULL, applicationShellWidgetClass,
- X Dis, NULL, 0);
- X top_form = XtCreateManagedWidget ("top form", formWidgetClass,
- X toplevel, NULL, 0);
- X surface = XtCreateManagedWidget ("drawing surface", simpleWidgetClass,
- X top_form, simple_args, XtNumber(simple_args));
- X XtRealizeWidget (toplevel);
- X
- X Win = XtWindow (surface);
- X XGetWindowAttributes (Dis, Win, &wattr);
- X Pix = XCreatePixmap (Dis, Win, WINDOW_WIDTH, WINDOW_HEIGHT, wattr.depth);
- X Pixsave = XCreatePixmap (Dis, Win, WINDOW_WIDTH, WINDOW_HEIGHT, wattr.depth);
- X XSelectInput (Dis, Win,
- X ExposureMask | ButtonPressMask | ButtonReleaseMask |
- X KeyPressMask | StructureNotifyMask );
- X
- X gc_def = DefaultGC (Dis, DefaultScreen (Dis));
- X assign_colors ();
- X XFlush (Dis);
- X
- X /* Initialize random number generator */
- X srand (time ((long *) 0)); /* initialize rand() */
- X seed16v[0] = rand(); seed16v[1] = rand(); seed16v[2] = rand();
- X seed48 (seed16v); /* initialize lrand48() */
- X
- X XFillRectangle (Dis, Pix, Gc[0], 0, 0, MAXX*SIZE, MAXY*SIZE); redraw ();
- X init (*++argv);
- X for (step=0; step<MAXSTEP; step++) {
- X onestep();
- X redraw();
- X checkmouse (); }
- X XtDestroyApplicationContext (appc);
- X return (0); }
- X
- X
- Xassign_colors () {
- X Colormap colormap; XColor screen_in_out,exact; int i;
- X
- X for (i=0; i<256; i++) greycols[i] = 4.0 + (double) i * 27.0 / 254.0;
- X for (i=0; i<16; i++) tecols[i] = 0;
- X for (; i<80; i++) tecols[i] = 4.0 + (double) (i-16) * 27.0 / 62.0;
- X for (; i<256; i++) tecols[i] = 1;
- X
- X colormap = DefaultColormap (Dis, DefaultScreen(Dis));
- X for (i=0; i < 32; i++) {
- X XAllocNamedColor (Dis, colormap, color_names[i], &screen_in_out, &exact);
- X Gc[i] = XCreateGC (Dis, Win, 0, (XGCValues *) NULL);
- X XSetForeground (Dis, Gc[i], screen_in_out.pixel);
- X if (i == 0) XSetForeground (Dis, gc_def, screen_in_out.pixel); } }
- X
- X
- X/* Each call to this routine dispatches any pending events. We are only
- X interested in expose events which require a redraw, and the letter 'q'
- X being pressed to quit. */
- Xcheckmouse () { XEvent e; char c; KeySym sym; XComposeStatus status;
- X
- X while (XtAppPending (appc)) { /* while there are events */
- X XtAppNextEvent (appc, &e); /* get one */
- X switch (e.type) { /* and process it */
- X case Expose:
- X if (e.xexpose.window != Win) XtDispatchEvent(&e);
- X else if (e.xexpose.count == 0) redraw ();
- X break;
- X case KeyPress:
- X XLookupString(&e,&c,1,&sym,&status);
- X switch (sym) {
- X case XK_q: step = MAXSTEP; break;
- X case XK_h: picktype = M_HEAT; break;
- X case XK_p: picktype = M_PRESS; break;
- X case XK_w: picktype = M_WIND; break;
- X case XK_r: picktype = M_RAIN; break;
- X case XK_c: picktype = M_CLIM; break; }
- X break;
- X default: XtDispatchEvent(&e); } } }
- X
- X
- Xredraw () {
- X XCopyArea (Dis, Pix, Win, Gc[0], 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
- X XFlush (Dis); }
- X
- X
- Xrnd (top) short top; { return (lrand48 () % top); }
- X
- X
- Xpanic (s) char *s; { printf ("PANIC: %s\n", s); exit (1); }
- X
- X
- Xdraw (ctype, ltype, cra, lra)
- X int ctype, ltype;
- X unsigned char cra[MAXX][MAXY], lra[MAXX][MAXY]; {
- X register short i, j, k, x; unsigned char *lut;
- X
- X switch (ctype) {
- X case DRAW_GREY: lut = greycols; break;
- X case DRAW_LAND: lut = landcols; break;
- X case DRAW_CLIM: lut = climcols; break;
- X case DRAW_TEC: lut = tecols; break; }
- X for (j=0; j < YSIZE; j++) for (i=0; i < XSIZE-1; i++) {
- X x = lut[cra[i][j]]; k = i+1;
- X while ((lut[cra[k][j]] == x) && (k < XSIZE-1)) k++;
- X XFillRectangle (Dis, Pix, Gc[x], i*SIZE, j*SIZE, (k-i)*SIZE, SIZE);
- X i = k-1; }
- X switch (ltype) {
- X case LINE_DIAG: diagonal (lra); break;
- X case LINE_CORN: corner (lra); break;
- X case LINE_NONE: break; } }
- X
- X
- X#define LEFT(i,j,x) \
- X XDrawLine (Dis, Pix, Gc[x], i*SIZE, j*SIZE, i*SIZE, (j+1)*SIZE)
- X#define ABOVE(i,j,x) \
- X XDrawLine (Dis, Pix, Gc[x], i*SIZE, j*SIZE, (i+1)*SIZE, j*SIZE)
- X#define UPLEFT(i,j,x) \
- X XDrawLine (Dis, Pix, Gc[x], i*SIZE, j*SIZE, (i+1)*SIZE, (j+1)*SIZE)
- X#define UPRIGHT(i,j,x) \
- X XDrawLine (Dis, Pix, Gc[x], (i+1)*SIZE, j*SIZE, i*SIZE, (j+1)*SIZE)
- X
- X
- Xdiagonal (ra) unsigned char ra[MAXX][MAXY]; { register short i, j;
- X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++)
- X switch (ra[i][j]) {
- X case 0: break;
- X case N: LEFT (i, j, 0); break;
- X case S: LEFT (i, j, 1); break;
- X case E: ABOVE (i, j, 1); break;
- X case W: ABOVE (i, j, 0); break;
- X case N|E: UPRIGHT (i, j, 0); break;
- X case N|W: UPLEFT (i, j, 0); break;
- X case S|E: UPLEFT (i, j, 1); break;
- X case S|W: UPRIGHT (i, j, 1); break; } }
- X
- X
- Xcorner (ra) unsigned char ra[MAXX][MAXY]; { register short i, j, x;
- X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++) {
- X x = ra[i][j];
- X if (x & LINE_0V) LEFT (i, j, 0);
- X else if (x & LINE_1V) LEFT (i, j, 1);
- X if (x & LINE_0H) ABOVE (i, j, 0);
- X else if (x & LINE_1H) ABOVE (i, j, 1); } }
- END_OF_FILE
- if test 7119 -ne `wc -c <'./src/x.c'`; then
- echo shar: \"'./src/x.c'\" unpacked with wrong size!
- fi
- # end of './src/x.c'
- fi
- echo shar: End of archive 3 \(of 4\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-