home
 
 
 
New Code
{
												New Code
												© Charles Chandler
												http://qdl.scs-inc.us/?top=9719
											}
											PROCEDURE Main;
											CONST
											dataFile = 'Plug-ins\CLC\Geophysics\Data\Solar Elements.txt';
											debugOutFile = 'debug.txt';
											debug = false;
											lastIndex = 82;
											xMax = lastIndex * 2;
											bezPrec = lastIndex;
											TYPE
											row = STRUCTURE
											sym :STRING; {element abbr}
											nam :STRING; {element name}
											den :REAL;   {density}
											apv :REAL;   {atoms per volume}
											set1 :REAL;  {Photosphere, from Anders & Grevesse (1989)}
											set2 :REAL;  {Solar Wind, from Manuel, Kamat, & Mozina (2006)}
											set3 :REAL;  {B2FH Values, from Manuel, Kamat, & Mozina (2006)}
											use :REAL;   {which set to use}
											cor :REAL;   {correction}
											vol :REAL;   {volume}
											rad :REAL;   {radius}
											END;
											VAR
											objName, noneClass, str :STRING;
											objHand, recHand, wallHand, pathHand, correctPoly :HANDLE;
											rows :ARRAY [0..lastIndex] OF row;
											bezier :ARRAY [1..bezPrec] OF POINT;
											p0, p1, p2, p3 :POINT;
											cnt, cnt1, cnt2, vertexType, zoomFactor :INTEGER;
											p1x, p1y, p2x, p2y, p3y :INTEGER;
											x, y, y1, y2, y3, lastX, nextX, thisX, thisY, corTop, corBot, vertexRadius, tmpReal :REAL;
											pt, begPt, endPt, lastPt, nextPt :POINT;
											totVol, correction, abundance, avgDen, decOfTotVol, totRad :REAL;
											correctPolyArray :DYNARRAY OF POINT;
											correctPolyCnt :INTEGER;
											pMinCor :INTEGER;
											t :REAL;
											bestPt1, bestPt2, bestPt3 :POINT;
											upperCore, lowerRadiative, upperRadiative, lowerConvective :REAL;
											scLower, scUpper, scDense, scTotal, previousScore :REAL;
											parallel, intOnLines :BOOLEAN;
											iterations :INTEGER;
											testMaxX, testMaxY, testMinX, testMinY :INTEGER;
											 
											{$Include ..\..\..\Common\Utilities_All.px}
											{$Include ..\..\..\Common\Utilities_Objects.px}
											 
											PROCEDURE CubicBezier(precision :INTEGER);
											VAR
											cnt :INTEGER;
											t, t2, t3 :REAL;
											BEGIN
											FOR cnt := 1 TO precision DO BEGIN
											t := cnt / precision;
											bezier[cnt]
											:= {p0 * ((1 - t) ^ 3) p0 is always 0,0 for us, so skip it}
											+  (p1 * ((1 - t) ^ 2) * 3 * (t    ))
											+  (p2 * ((1 - t)    ) * 3 * (t ^ 2))
											+  (p3                     * (t ^ 3));
											END;
											END;
											 
											FUNCTION RadiusOfSphere(volume :REAL) :REAL;
											BEGIN
											RadiusOfSphere := (volume / ((4 * PI) / 3)) ^ (1/3);
											END;
											 
											PROCEDURE Calculate(p1x, p1y, p2x, p2y, p3y :INTEGER);
											BEGIN
											iterations := iterations + 1;
											IF (p1x + p1y + p2x + p2y + p3y) > 0 THEN BEGIN
											p1.x := p1x;
											p1.y := p1y;
											p2.x := p2x;
											p2.y := p2y;
											p3.y := p3y;
											CubicBezier(bezPrec);
											END;
											 
											{Add the correction factors to the abundances,
											and calculate the volumes and the radii.}
											totVol := 0;
											FOR cnt := 0 TO lastIndex DO BEGIN
											abundance := 10 ^ (rows[cnt].use + rows[cnt].cor);
											abundance := abundance * 100000000;
											rows[cnt].vol := abundance / rows[cnt].apv;
											totVol := totVol + rows[cnt].vol;
											totRad := RadiusOfSphere(totVol);
											rows[cnt].rad := totRad;
											END;
											 
											{totRad is now the total radius, so now we can convert
												the rads to decimals of the total. And knowing the
											total volume, we can calculate the average density.}
											upperCore := 0;
											lowerRadiative := 0;
											upperRadiative := 0;
											lowerConvective := 0;
											avgDen := 0;
											FOR cnt := 0 TO lastIndex DO BEGIN
											rows[cnt].rad := rows[cnt].rad / totRad;
											IF  (rows[cnt].rad < .27 - .05) THEN upperCore      := rows[cnt].den;
											IF  (rows[cnt].rad < .70 - .05) THEN upperRadiative := rows[cnt].den;
											IF ((rows[cnt].rad > .27 + .05) AND (lowerRadiative  = 0)) THEN lowerRadiative  := rows[cnt].den;
											IF ((rows[cnt].rad > .70 + .05) AND (lowerConvective = 0)) THEN lowerConvective := rows[cnt].den;
											decOfTotVol := rows[cnt].vol / totVol;
											avgDen := avgDen + (decOfTotVol * rows[cnt].den);
											END;
											scDense := Abs(1408 - avgDen) / -1000;
											scLower := (upperCore - lowerRadiative)       / 2000;
											scUpper := (upperRadiative - lowerConvective) / 2000;
											scTotal := scDense + scLower + scUpper;
											IF (scTotal > previousScore) THEN BEGIN
											bestPt1 := p1;
											bestPt2 := p2;
											bestPt3 := p3;
											previousScore := scTotal;
											END;
											END;
											 
											PROCEDURE PlaceText(text :STRING; x, y, rot :REAL; just, vAlign :STRING);
											CONST
											isMirrored = false;
											VAR
											justInt, vAlignInt :INTEGER;
											BEGIN
											CreateText(text);
											SetTextOrientation(LNewObj, x, y, rot, isMirrored);
											IF (just = 'left'  ) THEN justInt := 1 ELSE
											IF (just = 'center') THEN justInt := 2 ELSE
											IF (just = 'right' ) THEN justInt := 3;
											SetTextJust(LNewObj, justInt);
											IF (vAlign = 'top'    ) THEN vAlignInt := 1 ELSE
											IF (vAlign = 'textTop') THEN vAlignInt := 2 ELSE
											IF (vAlign = 'center' ) THEN vAlignInt := 3 ELSE
											IF (vAlign = 'textBot') THEN vAlignInt := 4 ELSE
											IF (vAlign = 'bot'    ) THEN vAlignInt := 5;
											SetTextVerticalAlign(LNewObj, vAlignInt);
											END;
											 
											BEGIN
											IF GetCustomObjectInfo(objName, objHand, recHand, wallHand) THEN BEGIN
											SetObjectVariableBoolean(objHand, 800, TRUE);
											IF pZoom THEN zoomFactor := 5 ELSE zoomFactor := 1;
											 
											{Load the abundance data.}
											Open(dataFile);
											FOR cnt := 0 TO lastIndex DO BEGIN
											ReadLn(
											rows[cnt].sym,
											rows[cnt].nam,
											rows[cnt].den,
											rows[cnt].apv,
											rows[cnt].set1,
											rows[cnt].set2,
											rows[cnt].set3);
											END;
											Close(dataFile);
											FOR cnt := 0 TO lastIndex DO BEGIN
											IF pSet = '1' THEN rows[cnt].use := rows[cnt].set1 ELSE
											IF pSet = '2' THEN rows[cnt].use := rows[cnt].set2 ELSE
											IF pSet = '3' THEN rows[cnt].use := rows[cnt].set3;
											END;
											 
											IF (debug) THEN ReWrite(debugOutFile);
											IF (debug) THEN Close(debugOutFile);
											OpenPoly;
											 
											p0.x := 0;                p0.y := 0;
											p1.x := pControlPoint01X; p1.y := pControlPoint01Y;
											p2.x := pControlPoint02X; p2.y := pControlPoint02Y;
											p3.x := xMax;             p3.y := pControlPoint03Y;
											SetRField(objHand, objName, 'ControlPoint03X', Concat(xMax));
											IF ((pReCalc) and (false)) THEN BEGIN
											iterations := 0;
											previousScore := -100;
											testMinX := -10;
											testMinY := -50;
											testMaxX :=  200;
											testMaxY :=  50;
											FOR p1x := testMinX TO testMaxX DO BEGIN
											FOR p1y := testMinY TO testMaxY DO BEGIN
											FOR p2x := testMinX TO testMaxX DO BEGIN
											FOR p2y := testMinY TO testMaxY DO BEGIN
											FOR p3y := testMinY TO testMaxY DO BEGIN
											Calculate(p1x, p1y, p2x, p2y, p3y);
											END;
											END;
											END;
											END;
											END;
											p1 := bestPt1;
											p2 := bestPt2;
											p3 := bestPt3;
											Message('iterations: ', iterations);
											SetRField(objHand, objName, 'ControlPoint01X', Concat(p1.x));
											SetRField(objHand, objName, 'ControlPoint01Y', Concat(p1.y));
											SetRField(objHand, objName, 'ControlPoint02X', Concat(p2.x));
											SetRField(objHand, objName, 'ControlPoint02Y', Concat(p2.y));
											SetRField(objHand, objName, 'ControlPoint03Y', Concat(p3.y));
											SetRField(objHand, objName, 'ReCalc', 'False');
											END;
											CubicBezier(bezPrec);
											IF pShow_Bezier THEN BEGIN
											BeginPoly;
											AddPoint(0, 0);
											FOR cnt := 1 TO bezPrec DO BEGIN
											AddPoint(bezier[cnt].x, bezier[cnt].y);
											END;
											EndPoly;
											SetFPat(LNewObj, 0);
											SetPenFore(LNewObj, 65535, 0, 0);
											END;
											 
											{Get the vertices of the correction polyline.}
											pathHand := GetCustomObjectPath(objHand);
											ReshapablePath(objHand, pathHand);
											cnt := GetVertNum(pathHand);
											GetPolylineVertex(pathHand, cnt, x,           y, vertexType, vertexRadius);
											SetPolylineVertex(pathHand, cnt, xMax + .001, y, vertexType, vertexRadius, TRUE);
											pathHand := CopyPoly(pathHand);
											SetFPat(pathHand, 0);
											SetVertexVisibility(pathHand, GetVertNum(pathHand) - 1, FALSE);
											correctPoly := ConvertToPolygon(pathHand, 32);
											correctPolyCnt := GetVertNum(correctPoly);
											ALLOCATE correctPolyArray[1..correctPolyCnt];
											FOR cnt := 1 TO correctPolyCnt DO BEGIN
											GetPolyPt(correctPoly, cnt, pt.x, pt.y);
											correctPolyArray[cnt] := pt;
											END;
											DelObj(correctPoly);
											IF NOT pZoom THEN BEGIN
											FOR cnt := 1 to GetVertNum(pathHand) DO BEGIN
											GetPolylineVertex(pathHand, cnt, x,  y,     vertexType, vertexRadius);
											SetPolylineVertex(pathHand, cnt, x, -y / 5, vertexType, vertexRadius, TRUE);
											END;
											SetLS(pathHand, -1);
											END;
											 
											{Find y values along correction polyline.}
											begPt.y := 100;
											endPt.y := -100;
											FOR cnt1 := 0 TO lastIndex DO BEGIN
											begPt.x := cnt1 * 2;
											endPt.x := cnt1 * 2;
											correction := 0;
											FOR cnt2 := 1 to correctPolyCnt - 1 DO BEGIN
											lastPt := correctPolyArray[cnt2];
											nextPt := correctPolyArray[cnt2+1];
											LineLineIntersection(begPt, endPt, lastPt, nextPt, parallel, intOnLines, pt);
											IF ((NOT parallel) & (intOnLines)) THEN BEGIN
											correction := correction + (pt.y / 5);
											cnt2 := correctPolyCnt; {quit loop}
											END;
											END;
											rows[cnt1].cor := correction;
											END;
											 
											Calculate(0, 0, 0, 0, 0);
											 
											SetRField(objHand, objName, 'Density', Concat(avgDen));
											SetRField(objHand, objName, 'scDense', Concat(scDense));
											SetRField(objHand, objName, 'scLower', Concat(scLower));
											SetRField(objHand, objName, 'scUpper', Concat(scUpper));
											SetRField(objHand, objName, 'scTotal', Concat(scTotal));
											 
											{***********}
											{Graphics...}
											{***********}
											pMinCor := pMaxCor - 12;
											corTop := pMaxCor * zoomFactor;
											corBot := pMinCor * zoomFactor;
											 
											{Abundances.}
											y1 := corTop + 23;
											IF NOT pZoom THEN y1 := y1 - 25;
											TextSize(5);
											FOR cnt := 0 TO lastIndex DO BEGIN {element values and names}
											nextPt.x := cnt * 2;
											nextPt.y := rows[cnt].use + y1;
											Arc(nextPt.x - .2, nextPt.y + .2, nextPt.x + .2, nextPt.y - .2, 0, 360);
											IF cnt > 0 THEN LineTo(nextPt.x, nextPt.y) ELSE MoveTo(nextPt.x, nextPt.y);
											PlaceText(rows[cnt].nam, nextPt.x + .4, y1 - 3, -90, 'left', 'center');
											END;
											Rect(0, y1 - 2, xMax, y1 + 12); SetFPat(LNewObj, 0);
											FOR cnt := -2 TO 12 DO BEGIN {vertical tick marks}
											IF cnt MOD 2 = 0 THEN BEGIN
											MoveTo(0,  y1 + cnt); LineTo(   - 1, y1 + cnt);
											MoveTo(xMax, y1 + cnt); LineTo(xMax + 1, y1 + cnt);
											PlaceText(Concat(cnt), xMax + 3.5, y1 + cnt, 0, 'right', 'center');
											PlaceText(Concat(cnt),      - 1.5, y1 + cnt, 0, 'right', 'center');
											END;
											END;
											 
											{Corrections.}
											IF pZoom THEN BEGIN
											Rect(0, corBot, xMax, corTop); SetFPat(LNewObj, 0);
											FOR cnt := pMinCor TO pMaxCor DO BEGIN {vertical tick marks}
											IF cnt MOD 2 = 0 THEN BEGIN
											MoveTo(0,    cnt * zoomFactor); LineTo(     - 1, cnt * zoomFactor);
											MoveTo(xMax, cnt * zoomFactor); LineTo(xMax + 1, cnt * zoomFactor);
											PlaceText(Concat(cnt), xMax + 3.5, cnt * zoomFactor, 0, 'right', 'center');
											PlaceText(Concat(cnt),      - 1.5, cnt * zoomFactor, 0, 'right', 'center');
											END;
											END;
											END;
											 
											{y axis labels}
											TextSize(8);
											y3 := corBot - 50;
											FOR cnt := 0 TO 20 DO BEGIN
											MoveTo(0,    y3 + cnt); LineTo(     - 1, y3 + cnt);
											MoveTo(xMax, y3 + cnt); LineTo(xMax + 1, y3 + cnt);
											IF cnt MOD 2 = 0 THEN BEGIN
											IF cnt MOD 4 = 0 THEN BEGIN
											MoveTo(0,    y3 + cnt); LineTo(     - 2, y3 + cnt);
											MoveTo(xMax, y3 + cnt); LineTo(xMax + 2, y3 + cnt);
											PlaceText(Concat(cnt), xMax + 6.5, y3 + cnt + .1, 0, 'right', 'center');
											PlaceText(Concat(cnt),      - 2.5, y3 + cnt + .1, 0, 'right', 'center');
											END;
											END;
											END;
											 
											{density curve}
											MoveTo(0, (rows[0].den / 1000) + y3);
											FOR cnt := 1 TO lastIndex DO BEGIN
											LineTo(xMax * rows[cnt].rad, (rows[cnt-1].den / 1000) + y3);
											LineTo(xMax * rows[cnt].rad, (rows[cnt  ].den / 1000) + y3);
											END;
											 
											{Export results to a text file.}
											WriteLn('0.0000000000', Chr(9), rows[0].den);
											FOR cnt := 0 TO lastIndex DO BEGIN
											WriteLn(rows[cnt].rad, Chr(9), rows[cnt].den);
											IF (cnt < lastIndex) THEN WriteLn(rows[cnt].rad + 0.0000000001, Chr(9), rows[cnt + 1].den);
											END;
											 
											{primary elements}
											TextSize(9);
											MoveTo(0, y3 + 22); LineTo(thisX, y3 + 22 + 1);
											lastX := 0;
											FOR cnt := 0 TO lastIndex DO BEGIN
											thisX := xMax * rows[cnt].rad;
											thisY := y3 + 22;
											MoveTo(thisX, thisY); LineTo(thisX, thisY + 1);
											IF (thisX - lastX > 6) THEN BEGIN
											PlaceText(rows[cnt].sym, (thisX + lastX) / 2, thisY + .25, 0, 'center', 'bot');
											END;
											lastX := thisX;
											END;
											 
											FOR cnt := 0 TO 10 DO BEGIN
											MoveTo((cnt / 10) * xMax, y3 - 2); LineTo((cnt / 10) * xMax, y3 - 3);
											END;
											 
											IF pZoom THEN BEGIN
											TextSize(8);
											PlaceText(Concat('resulting average density: ', Round(avgDen), ' kg/m '), xMax * .500, corBot - 1, 0, 'center', 'top');
											TextSize(6);
											PlaceText('3', (xMax * .500) + 27.7, corBot - 1, 0, 'center', 'top');
											END;
											 
											Rect(0, y3 - 2, xMax, y3 + 22); SetFPat(LNewObj, 0);
											MoveTo(xMax * .27, y3 - 2); LineTo(xMax * .27, y3 + 22); SetLS(LNewObj, -1);
											MoveTo(xMax * .70, y3 - 2); LineTo(xMax * .70, y3 + 22); SetLS(LNewObj, -1);
											 
											TextSize(12);
											IF pSet = '1' THEN str := ' in Photosphere, from Anders & Grevesse (1989)' ELSE
											IF pSet = '2' THEN str := ' in Solar Wind, from Manuel, Kamat, & Mozina (2006)' ELSE
											IF pSet = '3' THEN str := ' in B2FH Values, from Manuel, Kamat, & Mozina (2006)';
											PlaceText(Concat('Log(Abundance)', str),    xMax * .500, y1    + 13, 0, 'center', 'bot');
											PlaceText('Density per Solar Radius', xMax * .500, y3    + 27, 0, 'center', 'bot');
											PlaceText('Core',            xMax * .135, y3 -  3, 0, 'center', 'top');
											PlaceText('Radiative Zone',  xMax * .485, y3 -  3, 0, 'center', 'top');
											PlaceText('Convective Zone', xMax * .850, y3 -  3, 0, 'center', 'top');
											 
											TextSize(10); PlaceText('Mg/m', 0, 0, 0, 'center', 'bot'); SetTextOrientation(LNewObj,  -7, y3 +  9, 90, false);
											TextSize( 8); PlaceText( '3',   0, 0, 0, 'center', 'top'); SetTextOrientation(LNewObj, -12, y3 + 15, 90, false);
											 
											IF NOT pZoom THEN BEGIN
											tmpReal := 17.5;
											thisX := (xMax / 2) - (192.04 / 2);
											thisY := y1 + 25;
											Rect(thisX, thisY, thisX + 192.04, thisY - 123.46 + 25); SetFPat(LNewObj, 0);
											END;
											END;
											END;
										RUN(Main);

← PREV Powered by Quick Disclosure Lite
© 2010~2021 SCS-INC.US
UP ↑