home *** CD-ROM | disk | FTP | other *** search
- unit GLFuncs;
- {============================================================}
- { Unit Title - Abstract OpenGL Window }
- { }
- { Codemaster - ohn Hutchings }
- { Date - 10/6/98 }
- { DeBugged - }
- { }
- {============================================================}
-
- {$V+,X+,F+,B-}
- {$IFDEF MinSize} {$S-,L-,R-,Q-,D-} {$ENDIF}
-
- {===============================================================================
-
- PURPOSE
-
- This unit defines some global types and functions used with OpenGL
-
- METHOD
-
- COMPILER DIRECTIVES
-
- MINSIZE limits debug and symbol info
-
- GLOBALS
-
- Classes
- Exceptions
- Variables
-
- Procedures
-
-
- Pass Through values
- 1000-1999 pOINTS
- 2000-2999 Lines
- 3000-3999 Ploygons
- 4000-4999 Polygon Text
- 5000-5999 Bitmap Text
- 6000-6999 Bitmaps
- 7000-7999 Textures
-
- Split value under here into HundredVal, TenVal, UnitVal and each code
- is meaningful to the category
- Points
- HundredVal = NotUsed
- TenVal = Size
- UnitVal = PointType
-
- Lines
- HundredVal = LineType
- TenVal = NotUsed
- UnitVal = LineWidth
-
- Polygons
- HundredVal = NotUsed
- TenVal = NotUsed
- UnitVal = Fill=1,
-
- PolygonText
- CharVal = 0-255 represents the text
- CharSize = Size of text in pixels
- UnitVal = NotUsed
-
- Bitmaps
-
- EXCEPTIONS
-
-
- NOTES
-
-
- ===============================================================================}
-
- (******* ******************************************************)
- interface
- (******* ******************************************************)
- {$W+}//set stack frames on as this seemms to help win95 access error
-
- uses Windows, sysutils, classes, Graphics, Math, openGL;
-
- Const
- //Size of general list
- glGeneralListSize=200;
- //Size of Text list
- glTextSize=256;
-
- //Fixed RenderCanvas Diplay List offset constants
- dlFullRenderMode=1;
- dlQuickRenderMode=2;
- dlBackground=3;
- dl2DWindow=4;
- dlForeGround=5;
-
- dlSimpleCube=12;
- dl2DGraphics=13;
- dlFullAxis=14;
- dlQuickAxis=15;
- dlBasicAxis=16;
- dlFocusedBorder=17;
- {dlUnFocusedBorder=18;}
- dlGridFront=19;
- dlGridBack=20;
- dlGridLeft=21;
- dlGridRight=22;
- dlGridTop=23;
- dlGridBottom=24;
- dlPointCross=25;
- dlPointX =26;
- dlPointsphere=27;
- dlSelectCube=28;
- dlLightsOn=29;
- dlLightsOff=30;
- dlXYCircle=31;
- dlXZCircle=32;
- dlYZCircle=33;
- dlLockedSelectCube=34;
- dlSimpleDiamond=35;
- dlYellowDiamond=36;
- dlRedDiamond=37;
-
-
- // glFeedBack buffer trial start size
- fbBufferSizetiny = 500000;
- fbBufferSizeLarge = 20000000;
-
- CursorPlaneSide = 10000;
- type
-
- GLToolMode =(tlNone,tlSelect,tlPoint,tlLine,tlPolyLine,tlPolygon,tlRectangle);
- //Set the current tool mode
- GLSelectState = (stNone,stButtonDown,stDrag,stStretch,stEdit,stPoly,stPolyClosed);
- //set when mouse moves objects
- GLMoveMode =(mmNone,mmMoveToPt,mmZoom,mmPan,mmFly,mmRotate,
- mmslide,mmLookAt,mmWalk,mmTwist,mmMeasure,
- mmModifyScreenZ,mmLookAtPt,mmViewPoints);
- //Move mode will have precedence over the current Tool mode
- GLRenderState =(rmFull,rmQuick,rmMotion,rmThread,rmAnimation,rmViewAnimate,fmGDIOnly);
- //current state for rendering, will be passed to evemnts
- GLRender =(rPoints,rWireframe,rBoundary,rFlat,rSmooth);
- // states for rendering
- GLMoveRender =(mrSameAsStationary,mrPoints,mrWireframe,mrBoundary,mrFlat,mrSmooth);
- //states for rendering if in motion
- GLBackground =(glWhiteBkgd,glBlackBkgd);
- //current background color will set black color as needed
- GLPointMode =(ptSimple,ptCross,ptX,ptShpere,ptCube);
- //how a point is drawn
- GLViewMode =(vmLookDown,vmLookUp,vmLookWest,vmLookEast,vwLookNorth,vmLookSouth,vmCustom);
- //fixed view modes can still move relative to these
- GLDriver =(eGeneric,eMiniClient,eInstallableClient);
- //not currently used
- GLGridType = (gtBottom,gtTop,gtLeftSide,gtRightSide,gtBack,gtFront);
- //Type of Grid boxes
- GLSaveState = (stAll,stDrawing,stLighting,stTexturing);
- // specify the state to save, stAll will save all
- GLLightType = (ltStd,ltSpot);
- // specify the type of the light
- GLStereoState = (steNone,steRedBlue,steBuffer);
- //current Stereo state
- vViewFrom= (vCentrePt,vLeftEye,vRightEye);
- // where is the current view point
- Type
- glColorVal =Array[1..4]of GlFloat;
-
- tgmf =Array[0..255] of tGlyphMetricsFloat;
- {Mode for dynamic creation of points}
-
- GLMatrixArrayd =Array[1..16] of GLDouble;
- GLMatrixArrayf =Array[1..16] of GLfloat;
- GLViewPortArray=Array[1..4] of GLInt;
-
- //array of RGB values from pixelread
- pGLRGB=^tGLRGB;
- tGLRGB= Array[1..3] of GLUByte;
-
- // array for storing feed back buffer data
- pFeedBackArray = ^tFeedBackArray;
- tFeedBackArray = Array[0..fbBufferSizeLarge]of single;
-
- pGLPoint = ^tGLPoint;
- tGLPoint = record X,Y,Z :GLDouble; end;
- //the GLPoint record structure
-
- tGLPointArray=Array of pGLPoint;
- //Dynamic array of GLPoints
-
- tGLLightVal = Record R,G,B,A : GLFloat; end;
-
- // record filled out by a call to the GLWin.GetMeasurementData
- tMeasureRecord= Record
- NoOfPoints :LongInt; //No of points used
- LastDeltaX, //dif in X
- LastDeltaY, //dif in Y
- LastDeltaZ, //dif in Z
- LastDistance, //Real dist
- Lastbearing, //Bearing of line degree
- LastElevation, //Elevation angle degree
- DistanceSum, //Sum of distance covered
- Area, //Area in the current plane
- CMX,CMY,CMZ //centre of mass location in current plane
- :Double;
- end;
-
- tPlaneEq = Record
- A,B,C,D:Single;
- isValid:Boolean;
- end;
-
- Const
- glMaroon : glColorVal=(0.5,0,0,1);
- glGreen : glColorVal=(0,0.5,0,1) ;
- glOlive : glColorVal=(0.5,0.5,0,1) ;
- glNavy : glColorVal=(0,0,0.5,1);
- glPurple: glColorVal=(0.5,0,0.5,1);
- glTeal : glColorVal=(0.5,0.5,0,1);
- glGray : glColorVal=(0.5,0.5,0.5,1);
- glSilver : glColorVal=(0.8,0.8,0.8,1);
- glRed : glColorVal=(1,0,0,1);
- glLime : glColorVal=(0,1,0,1);
- glYellow : glColorVal=(1,1,0,1);
- glBlue : glColorVal=(0,0,1,1);
- glFuchsia: glColorVal=(1,0,1,1);
- glAqua : glColorVal=(0,1,1,1);
- glLtGray : glColorVal=(0.7,0.7,0.7,1);
- glMidGray : glColorVal=(0.5,0.5,0.5,1);
- glDkGray : glColorVal=(0.25,0.25,0.25,1);
- glGray10 : glColorVal=(0.9,0.9,0.9,1);
- glGray20 : glColorVal=(0.8,0.8,0.8,1);
- glGray30 : glColorVal=(0.7,0.7,0.7,1);
- glGray40 : glColorVal=(0.6,0.6,0.6,1);
- glGray50 : glColorVal=(0.5,0.5,0.5,1);
- glGray60 : glColorVal=(0.4,0.4,0.4,1);
- glGray70 : glColorVal=(0.3,0.3,0.3,1);
- glGray80 : glColorVal=(0.2,0.2,0.2,1);
- glGray90 : glColorVal=(0.1,0.1,0.1,1);
- glWhite : glColorVal=(1,1,1,1);
-
- Var
- //Size of border around window - DONT change it
- fBorderWidth:SmallInt=2;
- //Start up size for Model block
- DefaultSize:Double=200;
- defaultAngle:Double=60;
-
- // no of segnents drawn in the axis set
- AxisRes:Smallint=10;
- MoveTolerance:Double=0.001;
- //tolerance for movement
- MouseMoveTol:SmallInt=6;
-
- glBlack : glColorVal=(0,0,0,1);
- // default black
- RotSensitivity :Integer =50;
- //sensitivity for rotation
-
- // default line types
- stContinous:gluShort=$FFFF;
- stDotted1:gluShort=$AAAA;
- stDashed:gluShort=$00FF;
- stDashDot:gluShort=$1C47;
- stDotted2:gluShort=$0101;
- stDotted3:gluShort=$0505;
- stDotted4:gluShort=$3333;
-
- //scale factor on the grid display
- Grid_Scale : Single=4;
-
- SnapDistance: GLDouble=5;
- // distance for gravity well
- fly_speed : Single= 5;
-
- // variables for setting up the pixel format to be used
- pix_ColorBits: Word=24;
- pix_DepthBits: Word=16;
- pix_StencilBits: Word=1;
- pix_AccumBits: Word=16;
-
- EyeOffset : Double = 1;//the offset from viewerposition for eye coordinates
- //currently as an angle in degrees
- MinCubeSize : Double=10;
- // min cube size setting
- Type
-
- // the light class contains GL Fundamentals for the lighting
-
- tGLLight = Class(TObject)
- Protected
- fPosition,
- fSpotDir : tGLPoint;
- fOn : Boolean;
- fLightNum : LongInt;
- // GL Name of Light
- fLightType : GLLightType;
- fAmbient,
- fDiffuse,
- fSpecular : tGLLightVal;
- fShininess : GLFloat;
- fSpotAngle,
- fSpotExponent : GLFloat;
-
- Public
- Constructor Create(aNum:LongInt);
- Destructor Destroy; Override;
- Procedure TurnLightOn;
- Procedure TurnLightOff;
- Procedure PositionLight(aPt:tGLPoint);
- Procedure SetUpLight;
- Procedure SetLightColor(aCol:tGLLightVal);
- Property IsOn:Boolean Read fOn;
- {Property Color:tGLLightVal Read Write}
- end;
-
- TLinkPoint = Class(TObject)
- Public
- X,Y,Z :GLDouble;
- SX,SY :LongInt; {GL Screen Coords}
- SPt :TPoint; {Windows screen coords}
- ScreenZ :Double; {Gl Screen Z}
- fScreenPtValid :Boolean;
-
- Constructor CreateSpecial(aWorldX,aWorldY,aWorldZ:Double);
- Function GetWorldPt:pGLDouble;
- Procedure SetHeight(aHt:LongInt);
- Function GetGLScreenPt(var aPt: TPoint):Boolean;
- Procedure SetGLScreenPt(AX,AY,aHt:LongInt;AZ:Double);
- Procedure SetWinScreenPt(aX,aY,aHt:LongInt;aZ:Double);
- Procedure SetWorldPt(aX,aY,aZ:Double);
- Function Duplicate:TLinkPoint;
- end;
-
- // General Routines
-
- Function GetGLStringValue(aext:GLInt):pchar;
- Function SetSwapHintAddress:Pointer;
-
- Procedure DrawAxes(SegLength,segDia,ArrowDia:glFloat;
- Const SegCount:GLInt; FullRender:Boolean);
-
- Procedure Scale_Data(Dmin, {data minimum}
- Dmax: Double; {data maximum}
- Nmax: Smallint; {max number of intervals}
- var st: Double; {starting value}
- var dinc: Double; {increment}
- var Ninc: Smallint); {number of increments}
-
- Procedure CreateGrid(MinPt,MaxPt:tGLPoint;aGridType:GLGridType;aStep:LongInt);
-
- Function Distancebetween(P1,p2:tGLPoint):Double;
-
- function PolygonArea(Polygon: TList): double;
- // assume a list of TLink points, will find the Plan area in the current screen plane
-
- Procedure GetListData(var aMeasRec:tMeasureRecord;aList:TList);
-
- procedure CalcPolarValues(P1,P2:tGLPoint;var Length,Bearing,Inclination:Single);
- // Calc the polar values for two GLPoints
- Procedure CalcEndPoint(P1:tGLPoint;Length,Bearing,Inclination:Single;Var P2:tGLPoint);
- // calc end point(P2) from polar and startpoint(P1)
-
- function MaskX86Exceptions: Pointer;
- procedure RestoreX86Mask(dwOldMask: Pointer);
- // from Delphi mag fix for Divide by zero
-
-
- Function BearingAndAzimuth(const P1,P2:tGLPoint;var Bearing,Azimuth:Double):Boolean;
- {Given 2 points return the bearing and azimuth}
- Function AngleFromVertical(const P1,P2:tGLPoint; var Angle:Double):Boolean;
- {given}
- function IsPtInsideList(x,y:LongInt;aList:tList):boolean;
- { return true if x,y is inside polygon
- List must contain a list of tlinkpoints assumed to be closed
- Most form a simple polygon}
- function intersects(x1,y1,x2,y2,u1,v1,u2,v2: Double;
- var lambda: Double ) : boolean;
- { check if two line segments (x1,y1)to(x2,y2) and (u1,v1)to(u2,v2) cross,
- if so return true and lambda ie x1,y1 lambda=0 x2,y2 lambda=1 }
- function HorzIntersects(x1,y1,x2,y2,u1,v1,u2: Double;
- var lambda: Double ) : boolean;
-
- Function CalcUnitNormal(P1,P2,P3:tGLPoint;var N:tGLPoint):Boolean;
- // calc the unit normal for the three supplied points
- // will be false if say points are in a line
- Procedure SetGLPointVal(Var aPt:tGLPoint;XVal,YVal,ZVal:Double);
- //set the tGLPoint values
-
- Procedure DrawFeedBackDataToCanvas(aCanvas : TCanvas; //canvas to draw on
- aSize : Integer; //amount of data
- FeedBack : pFeedBackArray;//arrray holding data
- FeedBackType: Longint; //data record type
- aHeight : Integer; //current window height (need to draw with GDI coordinates)
- aBitMaps : tList; //list of bitmaps to be drawn
- XScale,YScale:Double); // point scale factor
- // parse the data in feedback array according to the feedback type and draw to canvas
- function CalcPlaneEq(v1x,v1y,v1z,
- v2x,v2y,v2z,
- v3x,v3y,v3z:Double;
- Var fPlaneEq:tPlaneEq): boolean;
- (******* ******************************************************)
- implementation
- (******* ******************************************************)
- (******* ******************************************************)
- Const
- pi180:double=pi/180;
- CompareTol =0.001; { two points identical if within this of each other }
- SmallDivisor = 0.001; {check for parallel case in PlaneIntercept}
-
-
- {*********************************************************}
- {********************************************************}
- function Det3x3( { calc determinant of 3x3 matrix }
- a,b,c, { matrix elements }
- d,e,f,
- g,h,i: Double):Double;
- begin
- Result:=a*(e*i-f*h)-b*(d*i-f*g)+c*(d*h-e*g);
- end;
- {*********************************************************}
- function CalcPlaneEq(v1x,v1y,v1z,
- v2x,v2y,v2z,
- v3x,v3y,v3z:Double;
- Var fPlaneEq:tPlaneEq): boolean;
- var
- d1: Double;
- begin
- Result:=False;
- {calc plane equation ax+by+cz=d}
- {JH MOD 1/10/97}
- with fPlaneEq do
- Begin
- a:= det3x3(v1Y,V1Z,1.0,
- V2Y,V2Z,1.0,
- V3Y,V3Z,1.0);
-
- B:=-det3x3(V1X,V1Z,1.0,
- V2X,V2Z,1.0,
- V3X,V3Z,1.0);
-
- C:= DET3X3(V1X,V1Y,1.0,
- V2X,V2Y,1.0,
- V3X,V3Y,1.0);
-
- {normalise vector equation}
- d1:= sqrt(a*a + b*b + c*c);
- if abs(d1)<SmallDivisor then
- begin
- d:=0;
- IsValid:=False;
- end else
- begin
- with fPlaneEq do
- begin
- a:= a/d1; b:= b/d1; c:= c/d1;
- {now calculate constant in plane equation}
- d:=a*V1X + b*V1y + c*v1z;
- IsValid:=True;
- Result:=True;
- end;
- end;
- end;
- end;
- {********************************************}
- Procedure DrawFeedBackDataToCanvas(aCanvas:TCanvas;aSize:Integer;FeedBack:pFeedBackArray;
- FeedBackType:Integer;aHeight:Integer;
- aBitMaps : tList; //list of bitmaps to be drawn
- XScale,YScale:Double); // point scale factor
- // parse the data in feedback array according to the feedback type and draw to canvas
- Var Count,CVal:Integer;
- OldPenCol:TColor;
- OldBrushCol:TColor;
- CUserVal:Longint;
- T1,T2:TPoint;
- C1,C2:tColor;
- UnitVal,TenVal,HundredVal,ThousVal,CharVal,CharSize:Single;
- // scale the point value based on the supplied XScale,YScale
- Procedure ScalePoint(aPt:tPoint);
- Begin
- aPt.X:=round(aPt.X*XScale);
- aPt.Y:=Round(aPt.Y*YScale);
- end;
-
- Procedure ReadPoint(Var aPt:TPoint;Var aCol:Tcolor);
- Var R,G,B:Byte;
- R1,G1,B1:Single;
- Begin
- aCol:=clBlack;
- aPt.X:=0;aPt.Y:=0;
- aPt.X:=Round(FeedBack^[Count]);
- Inc(Count); //jump the XVal
- aPt.Y:=aHeight-Round(FeedBack^[count]);
- Inc(Count); //jump the Y Val
- If FeedBackType>=GL_3D then
- Begin
- inc(Count); // jump the Z val
- If FeedBackType>=GL_3D_COLOR then
- Begin
- R1:= FeedBack^[Count];
- inc(Count); // jump the R val
- G1:= FeedBack^[Count];
- inc(Count); // jump the G val
- B1:= FeedBack^[Count];
- inc(Count); // jump the B val
- R:=Round(R1*255);G:=Round(G1*255);B:=Round(B1*255);
- // set to black if white
- If (R=255)and (G=255) and (B=255) then
- aCol:=clBlack else
- aCol:=PaletteRGB(R,G,B);
- inc(Count); // jump the A Level
- If FeedBackType>=GL_3D_COLOR_TEXTURE then
- Begin
- inc(Count); // jump the val
- inc(Count); // jump the val
- inc(Count); // jump the val
- inc(Count); // jump the val
- end; //GL_3D_COLOR_TEXTURE
- end;//GL_3D_COLOR
- end; //GL_3D
- ScalePoint(aPt);
- end;
-
- Procedure ExtractValues(aVal:LongInt);
- Begin
- UnitVal:=0;TenVal:=0;HundredVal:=0;ThousVal:=0;CharVal:=0;
- CharSize:=0;
- If aVal=0 then exit;
- UnitVal:=Frac(aVal/10)*10;
- TenVal :=Frac(aVal/100)*100-UnitVal;
- CharVal:=Frac(aVal/1000)*1000;
- HundredVal:=CharVal-TenVal-UnitVal;
- ThousVal:=Frac(aVal/10000)*10000-charVal;
- CharSize:=ThousVal;
- end;
-
- Procedure MakePoint;
- Begin
- Inc(Count);
- ReadPoint(T1,C1);
- With aCanvas do
- Begin
- Pen.Color:=C1;
- MoveTo(T1.X,T1.Y);
- LineTo(T1.X+1,T1.Y+1);
- end;
- CUserVal:=0;
- end;
- Procedure MakeLine;
- Begin
- Inc(Count);
- ReadPoint(T1,C1);
- ReadPoint(T2,C2);
- With aCanvas do
- Begin
- Pen.Color:=C1;
- MoveTo(T1.X,T1.Y);
- LineTo(T2.X,T2.Y);
- end;
- CUserVal:=0;
- end;
- Procedure MakePolygon;
- Var PolyC,j: Integer;
- PolyPts: Array of TPoint;
- Begin
- Inc(Count);
- PolyC:= Round(FeedBack^[Count]);
- inc(Count);
- SetLength(PolyPts,PolyC);
- For j:=0 to PolyC-1 Do
- Begin
- ReadPoint(PolyPts[j],C1);
- end;
- With aCanvas do
- Begin
- Brush.Color :=C1;
- If CUserVal>0 then Brush.Style :=bsClear;
- Pen.Color :=C1;
- PolyGon(PolyPts);
- end;
- Finalize(PolyPts);
- CUserVal:=0;
- end;
- Procedure MakeBitMap ;
- Begin
- Inc(Count);
- ReadPoint(T1,C1);
- If assigned(aBitMaps) and (aBitMaps.Count>0) then
- With aCanvas do
- Begin
- Pen.Color:=C1;
- MoveTo(T1.X,T1.Y);
- {Draw(
- Ned to get the bitmap and draw
- }
- end;
- CUserVal:=0;
- end;
- Procedure MakeDraw ;
- Begin
- Inc(Count);
- CUserVal:=0;
- end;
- Procedure MakeCopy ;
- Begin
- Inc(Count);
- CUserVal:=0;
- end;
-
-
- Begin
- If not Assigned(aCanvas) then exit;
- If aSize=0 then exit;
- Count:=0;
- OldPenCol := aCanvas.Pen.Color;
- OldBrushCol:= aCanvas.Brush.Color;
- CUserVal:=0;
- Repeat
- CVal:=Round(FeedBack^[Count]);
- Case CVal of
- GL_PASS_THROUGH_TOKEN :Begin
- Inc(Count);
- CUserVal:=Round(FeedBack^[Count]);
- ExtractValues(CUserVal);
- Inc(Count);
- end ;
- GL_POINT_TOKEN :MakePoint;
- GL_LINE_TOKEN :MakeLine;
- GL_POLYGON_TOKEN :MakePolyGon;
- GL_BITMAP_TOKEN :MakeBitMap;
- GL_DRAW_PIXEL_TOKEN :MakeDraw;
- GL_COPY_PIXEL_TOKEN :MakeCopy;
- GL_LINE_RESET_TOKEN :Begin
- Case CUserVal of
- 1001..1009 :aCanvas.Pen.Width:=CUserVal-1000;
- //set pen width
- else aCanvas.Pen.Width:=1;
- end;
- MakeLine;
- end;
- else inc(Count);
- end;
- until (Count>=aSize-2);
- aCanvas.Pen.Color :=OldPenCol;
- aCanvas.Brush.Color :=OldBrushCol;
- end;
- {********************************************}
- {********************************************}
- function HorzIntersects(x1,y1,x2,y2,u1,v1,u2: Double;
- var lambda: Double ) : boolean;
- const
- eps = 1e-6;
- var
- mu,
- det: Double;
-
- begin
- Result:=false;
- lambda:=-1e6;
- { check if no overlap of coordinate ranges }
- if ((x1>=x2) and ((u1<=u2)and(u1>x1) or (u2<u1)and(u2>x1)))or
- ((x2>x1) and ((u1<=u2)and(u1>x2) or (u2<u1)and(u2>x2)))or
- ((y1>=y2) and (v1>y1))or ((y2>y1) and (v1>y2)) then exit;
-
- det:=-(u2-u1)*(y2-y1);
- if det=0 then exit;
- lambda:=(-(u2-u1)*(v1-y1))/det;
- mu:=((u1-x1)*(y2-y1)-(x2-x1)*(v1-y1))/det;
- if (lambda>-eps)and(lambda<1.0+eps)and
- (mu>-eps)and(mu<1.0+eps) then Result:=true;
- end;
- {********************************************}
- Function CalcUnitNormal(P1,P2,P3:tGLPoint;var N:tGLPoint):Boolean;
- // calc the unit normal for the three supplied points
- // will be false if say points are in a line
- Var T1,T2:tGLPoint;
- Length:Extended;
- Begin
- Result:=False;
-
- T1.X:=P1.X-P2.X;
- T1.Y:=P1.Y-P2.Y;
- T1.Z:=P1.Z-P2.Z;
-
- T2.X:=P2.X-P3.X;
- T2.Y:=P2.Y-P3.Y;
- T2.Z:=P2.Z-P3.Z;
-
- N.X:=(T1.Y*T2.Z) - (T1.Z*T2.Y);
- N.Y:=(T1.Z*T2.X) - (T1.X*T2.Z);
- N.Z:=(T1.X*T2.Y) - (T1.Y*T2.X);
- //set unit length
- Length:=Sqrt(sqr(N.X)+Sqr(N.Y)+Sqr(N.Z));
- If Length=0 then exit;
- N.X:=N.X/Length;
- N.Y:=N.Y/Length;
- N.Z:=N.Z/Length;
- Result:=True;
- end;
- {********************************************}
- function intersects(x1,y1,x2,y2,u1,v1,u2,v2: Double;
- var lambda: Double ) : boolean;
- { check if two line segments (x1,y1)to(x2,y2) and (u1,v1)to(u2,v2) cross,
- if so return true and lambda ie x1,y1 lambda=0 x2,y2 lambda=1 }
- const
- eps = 1e-6;
- var
- mu,
- det: Double;
-
- begin
- Result:=false;
- lambda:=-1e6;
- { check if no overlap of coordinate ranges }
- if ((x1>=x2) and ((u1<=u2)and(u1>x1) or (u2<u1)and(u2>x1)))or
- ((x2>x1) and ((u1<=u2)and(u1>x2) or (u2<u1)and(u2>x2)))or
- ((y1>=y2) and ((v1<=v2)and(v1>y1) or (v2<v1)and(v2>y1)))or
- ((y2>y1) and ((v1<=v2)and(v1>y2) or (v2<v1)and(v2>y2))) then exit;
-
- det:=(x2-x1)*(v2-v1)-(u2-u1)*(y2-y1);
- if det=0 then exit;
- lambda:=((u1-x1)*(v2-v1)-(u2-u1)*(v1-y1))/det;
- mu:=((u1-x1)*(y2-y1)-(x2-x1)*(v1-y1))/det;
- if (lambda>-eps)and(lambda<1.0+eps)and
- (mu>-eps)and(mu<1.0+eps) then Result:=true;
- end;
- (*************************************************************)
- function IsPtInsideList(x,y:LongInt;aList:tList):boolean;
- { return true if x,y is inside polygon
- List must contain a list of tlinkpoints assumed to be closed
- Most form a simple polygon}
- const
- eps = 1e-6;
- var
- lambda:double;
- iseg,
- nc,i: longint;
- pt1,
- pt2: TPoint;
- XMax,YMax,XMin,YMin:Longint;
- begin
- Result:=false;
- if not Assigned(aList) or (aList.count=0) then exit;
- //find max min values
- XMax:=Low(LongInt);YMax:=Low(LongInt);
- XMin:=High(LongInt);YMin:=High(LongInt);
- for i:=0 to aList.count-1 do
- begin
- Pt1.X:=tlinkPoint(aList.Items[i]).Spt.X;
- Pt1.Y:=tlinkPoint(aList.Items[i]).Spt.Y;
- If Pt1.X>XMax then XMax:=Pt1.X;
- If Pt1.Y>YMax then YMax:=Pt1.Y;
- If Pt1.X<XMin then XMin:=Pt1.X;
- If Pt1.Y<YMin then YMin:=Pt1.Y;
- end;
- if (x>xmax)or(y>ymax)or(x<xmin)or(y<ymin) then exit;
-
- { find if point is inside boundary or not by counting number of line crossings}
- nc:=0;
- for iseg:=0 to aList.count-2 do
- begin
- pt1:=tLinkPoint(aList.Items[iseg]).SPt;
- pt2:=tLinkPoint(aList.Items[iseg+1]).SPt;
- if Horzintersects(pt1.x,pt1.y,pt2.x,pt2.y,xmin,y,x,lambda) then
- begin
- if (lambda>eps)and(lambda<=1.0-eps) then inc(nc)
- else
- if (lambda<=eps)and(lambda>-eps) then
- begin
- if iseg=0 then pt1:=tLinkPoint(aList.Items[aList.count-2]).SPt
- else pt1:=tLinkPoint(aList.Items[iseg-1]).SPt;
- Horzintersects(pt1.x,pt1.y,pt2.x,pt2.y,xmin,y,x,lambda);
- if (lambda>-eps)and(lambda<1.0+eps) then inc(nc);
- end;
- end;
- end;
- if (nc mod 2 = 1) then Result:=true;
- end;
- {********************************************}
- Procedure SetGLPointVal(Var aPt:tGLPoint;XVal,YVal,ZVal:Double);
- //set the tGLPoint value
- Begin
- aPt.X:=XVal;
- aPt.Y:=YVal;
- aPt.Z:=ZVal;
- end;
- {********************************************}
-
- Function BearingAndAzimuth(const P1,P2:tGLPoint;var Bearing,Azimuth:Double):Boolean;
- Var XDif,YDif,ZDif,HDist:Extended;
- Begin
- Result:=False;
- XDif:=P2.X-P1.X; YDif:=P2.Y-P1.Y; ZDif:=P2.Z-P1.Z;
- HDist:=sqrt(sqr(XDif)+sqr(YDif));
- If YDif<>0 then Bearing:=ArcTan(abs(XDif)/abs(YDif))/pi180 else bearing:=0;
- If ZDif<>0 then Azimuth:=arcTan(HDist/ZDif)/pi180 else Azimuth:=0;
- If (XDif=0) and(YDif=0) then exit;
- If XDif>=0 then
- Begin
- If YDif>=0 then Bearing:=Bearing else Bearing:=180-Bearing;
- end else
- If XDif<0 then
- Begin
- If YDif>0 then Bearing:=360-Bearing else Bearing:=270-Bearing;
- end;
- Result:=True;
- end;
- {********************************************}
- Function AngleFromVertical(const P1,P2:tGLPoint; var Angle:Double):Boolean;
- Var XDif,YDif,ZDif,HDist:Extended;
- Begin
- Result:=False;
- Angle:=0;
- XDif:=P1.X-P2.X; YDif:=P1.Y-P2.Y; ZDif:=P1.Z-P2.Z;
- HDist:=sqrt(sqr(XDif)+sqr(YDif));
- If (HDist=0) then exit;
- Angle:=ArcTan(ZDif/HDist)/pi180;
- Result:=True;
- end;
-
- {********************************************}
- function MaskX86Exceptions: Pointer;
- var
- dwOldMask: Pointer;
- begin
- asm
- fnstcw WORD PTR dwOldMask;
- mov eax, dwOldMask;
- or eax, $3f;
- mov WORD PTR dwOldMask + 2, ax;
- fldcw WORD PTR dwOldMask + 2;
- end;
- result := dwOldMask;
- end;
- (******* ******************************************************)
-
- procedure RestoreX86Mask(dwOldMask: Pointer);
- begin
- asm
- fnclex;
- fldcw WORD PTR dwOldMask;
- end;
- end;
- (******* ******************************************************)
- procedure CalcPolarValues(P1,P2:tGLPoint;var Length,Bearing,Inclination:Single);
- // zero north, zero=horizontal
- var
- XDif,YDif,ZDif, HorDist,Pi180 : Double;
- begin
- Pi180:=Pi/180;
- XDif:= (P1.X-P2.X);
- YDif:= (P1.Y-P2.Y);
- ZDif:= (P1.Z-P2.Z);
- HorDist := SQRT(Sqr(XDif)+Sqr(YDif));
- Length := Sqrt(Sqr(HorDist)+Sqr(ZDif));
- Bearing:=arcTan2(Ydif,XDif)/pi180;
- If Bearing<0 then Bearing:=360+Bearing;
- Inclination:=arcTan2(-Zdif,HorDist)/pi180;
- {Tim B change for correct convention}
- Inclination:=Inclination-90{-VertAngle};
- end;
- (******************************************************)
- Procedure CalcEndPoint(P1:tGLPoint;Length,Bearing,Inclination:Single;Var P2:tGLPoint);
- // calc end point(P2) from polar and startpoint(P1)
- var
- HorDist,
- CompareTol : Double;
- begin
- CompareTol:=0.001;
-
- if Length <= CompareTol then
- begin
- P2.X:=P1.X;
- P2.Y:=P1.Y;
- P2.Z:=P1.Z;
- end else
- begin
- p2.z:=P1.z-(cos(Pi180*(90+Inclination))*Length);
- HorDist := (Sin(Pi180*(90+Inclination)))*Length ;
- P2.X := P1.X+(Sin(Bearing*Pi180))*HorDist;
- P2.Y := P1.Y+(Cos(Bearing*Pi180))*HorDist;
- {$B+}
- If (P2.x<comparetol)and(P2.x>-Comparetol) then P2.x:=0;
- If (P2.y<comparetol)and(P2.y>-Comparetol) then P2.y:=0;
- If (P2.z<comparetol)and(P2.Z>-Comparetol) then P2.z:=0;
- {$B-}
- end;
- end;
- (******************************************************)
- Procedure GetListData(var aMeasRec:tMeasureRecord;aList:TList);
- //Used to fill record with current move point data
-
- Procedure CalculateArea(Var Area,CMX,CMY,CMZ,DistanceSum:Double);
- Var TmpArea,TmpEast,TmpNorth,TmpElevation,CT,PX,PY,Pz:Double;
- iVal:LongInt;
- P1:tLinkPoint;
- Begin
- Area:=0;
- CMX:=0;CMY:=0;CMZ:=0;
- TmpArea:=0;
- TmpEast:=0;
- TmpNorth:=0;
- TmpElevation:=0;
- DistanceSum:=0;
- Px:=TLinkPoint(aList.Items[aList.count-1]).X ;
- Py:=TLinkPoint(aList.Items[aList.count-1]).Y ;
- pz:=TLinkPoint(aList.Items[aList.count-1]).Z ;
- For iVal:=0 to aList.Count-1 do
- Begin
- P1:= TLinkPoint(aList.Items[iVal]);
- DistanceSum:=DistanceSum+sqrt(Sqr(Px-P1.x)+sqr(Py-P1.y)+sqr(pz-P1.Z));
- CT:=PX*P1.Y - PY*P1.X;
- TmpArea:=TmpArea+CT;
- TmpEast:=TmpEast+CT*(PX+P1.X);
- TmpNorth:=TmpNorth+CT*(PY+P1.Y);
- TmpElevation:=TmpElevation+ P1.Z;
- PX:=P1.X;
- PY:=P1.Y;
- end;
- { Get Area and center of mass in the current square units }
- if abs(TmpArea)<0.001 then exit;
- CT:=TmpArea*3.0;
- CMX:=TmpEast/CT;
- CMY:=TmpNorth/CT;
- CMZ:=TmpElevation/aList.Count;
- Area:=abs(0.5*TmpArea) ;
- end;
-
- Var LP1,LP2:tLinkPoint;
- Begin
- FillChar(aMeasRec,SizeOf(aMeasRec),0);
- If aList.Count<2 then exit;
- // get last 2 points
- Lp1:=aList.Items[aList.count-2] ;
- Lp2:=aList.Items[aList.count-1] ;
- With ameasRec do
- Begin
- NoOfPoints := aList.Count; //No of points used
- LastDeltaX := Lp2.X-LP1.X; //dif in X
- LastDeltaY := Lp2.Y-LP1.Y; //dif in Y
- LastDeltaZ := Lp2.Z-LP1.Z; //dif in Z
- LastDistance:=sqrt( sqr(LastDeltaX)+sqr(LastDeltaY)+sqr(LastDeltaY)); //Real dist
- // to Do
- (* Lastbearing, //Bearing of line degree
- LastElevation, //Elevation angle degree*)
- If (aList.Count>2) then CalculateArea(Area,CMX,CMY,CMZ,DistanceSum);
- end;
- end;
- {*********************general routines******************************}
- function PolygonArea(Polygon: TList): double;
-
- function MySucc(n,Count: LongInt): LongInt;
- { returns next in series 123..Count123 }
- begin
- if n=Count then Result := 1
- else Result := n+1;
- end;
-
- function MyPrev(n,Count: LongInt): LongInt;
- { returns previous in series 123..Count123 }
- begin
- if n=1 then Result := Count
- else Result := n-1;
- end;
-
- var
- i: integer;
- PPrev, P, PSucc: TLinkPoint;
- Area: double;
- begin
- Area:= 0;
- for i:= 1 to Polygon.Count-1 do
- begin
- PPrev:= Polygon.Items[MyPrev(i,Polygon.Count)-1];
- P:= tLinkPoint(Polygon.Items[i-1]);
- PSucc:= Polygon.Items[MySucc(i,Polygon.Count)-1];
- Area:= Area + abs(P.X * (PSucc.Y - PPrev.Y));
- end;
- Result:= Area * 0.5;
- end;
- {*********************general routines******************************}
- Function DistanceBetween(P1,p2:tGLPoint):Double;
- Begin
- Result:=Sqrt(Sqr(P1.X-P2.X)+
- Sqr(P1.Y-P2.Y)+
- Sqr(P1.Z-P2.Z));
- end;
- (******* ******************************************************)
- Function GetGLStringValue(aext:GLInt):pchar;
- Begin
- Result:=glGetString(aext);
- end;
- (******* ******************************************************)
- Function SetSwapHintAddress:Pointer;
- const PC2 : pchar='GL_WIN_swap_hint';
- var PC1 : pChar;
- Begin
- Result:=nil;
- pc1:=GetGLStringValue(GL_EXTENSIONS);
- If StrPos(PC1,PC2)<>nil then
- Result:=wglGetProcAddress('');
- end;
- {**********************************************************************}
- Procedure DrawAxes(SegLength,segDia,ArrowDia:glFloat;
- Const SegCount:GLInt;FullRender:Boolean);
- var Quad:GLUquadricObj;
- Begin
- glPushAttrib(GL_ALL_ATTRIB_BITS);
- Quad:=gluNewQuadric;
- If fullRender then
- Begin
- gluQuadricDrawStyle(Quad,GLU_fill);
- gluQuadricNormals(Quad,GLU_SMOOTH);
- end else
- Begin
- gluQuadricDrawStyle(Quad,GLU_LINE);
- gluQuadricNormals(Quad,GLU_NONE);
- end;
- glColor4fv(@glRed); {X Axis}
- glPushMatrix;
- glTranslatef(0,0,0);
- glRotatef(90,0.0,1.0,0.0);
- gluCylinder(quad,segDia,segDia,SegLength,SegCount,SegCount);
- glPopMatrix;
- glPushMatrix;
- glTranslatef(SegLength,0,0);
- glRotatef(90,0.0,1.0,0.0);
- gluCylinder(quad,ArrowDia,0.0,SegLength,SegCount,SegCount);
- glPopMatrix;
- glColor4fv(@glBlue); {Y Axis}
- glPushMatrix;
- glTranslatef(0,0,0);
- glRotatef(-90,1.0,0.0,0.0);
- gluCylinder(quad,segDia,segDia,SegLength,SegCount,SegCount);
- glPopMatrix;
- glPushMatrix;
- glTranslatef(0,SegLength,0);
- glRotatef(-90,1.0,0.0,0.0);
- gluCylinder(quad,ArrowDia,0.0,SegLength,SegCount,SegCount);
- glPopMatrix;
- glColor4fv(@glGreen); {z Axis}
- glPushMatrix;
- glTranslatef(0,0,0);
- gluCylinder(quad,segDia,segDia,SegLength,SegCount,SegCount);
- glPopMatrix;
- glPushMatrix;
- glTranslatef(0,0,SegLength);
- gluCylinder(quad,ArrowDia,0.0,SegLength,SegCount,SegCount);
- glPopMatrix;
- gluDeleteQuadric(Quad);
- glPopAttrib;
- end;
- {**********************************************************}
- {**********************************************************}
- Constructor tGLLight.Create(aNum:LongInt);
- const DefVal1=0.5;
- DefVal2=1.0;
- defval3=0.0;
- Begin
- Inherited create;
- //default values
- With fPosition do
- Begin
- X:=0;Y:=0; Z:=1000;
- end;
- With fSpotDir do
- Begin
- X:=0;Y:=0;Z:=-1;
- end;
- With fAmbient do
- Begin
- R:=DefVal2;G:=DefVal2;B:=DefVal2;A:=DefVal2;
- end;
- With fDiffuse do
- Begin
- R:=DefVal2;G:=DefVal2;B:=DefVal2;A:=DefVal2;
- end;
- With fSpecular do
- Begin
- R:=DefVal2;G:=DefVal2;B:=DefVal2;A:=DefVal2;
- end;
- fShininess :=128;
-
- fLightNum:=aNum;
- fSpotExponent:=100;
- fSpotAngle:=60;
-
- end;
- {**********************************************************}
- Destructor tGLLight.Destroy;
- Begin
- Inherited Destroy;
- end;
- {**********************************************************}
- Procedure tGLLight.TurnLightOn;
- Begin
- fOn:=True;
- glEnable(fLightNum);
- SetUpLight;
- end;
- {**********************************************************}
- Procedure tGLLight.TurnLightOff;
- Begin
- fOn:=False;
- glDisable(fLightNum);
- end;
- {**********************************************************}
- Procedure tGLLight.PositionLight(aPt:tGLPoint);
- Begin
- fPosition:=aPt;
- SetUpLight;
- end;
- {**********************************************************}
- Procedure tGLLight.SetLightColor(aCol:tGLLightVal);
- Begin
- fAmbient:=aCol;
- fDiffuse:=aCol;
- fSpecular:=aCol;
- SetUpLight;
- end;
- {**********************************************************}
- Procedure tGLLight.SetUpLight;
- Begin
- If not fOn then exit;
- //assume GL session
- glLightfv(fLightNum,GL_POSITION,@fPosition);
- glLightfv(fLightNum,GL_Diffuse,@fDiffuse);
- glLightfv(fLightNum,GL_AMBIENT,@fAmbient);
- glLightfv(fLightNum,GL_Specular,@fSpecular);
- If fLightType=ltSpot then
- Begin
- glLightfv(fLightNum,GL_SPOT_DIRECTION,@fSpotDir);
- glLightf(fLightNum, GL_SPOT_CUTOFF,fSpotAngle);
- glLightf(fLightNum, GL_SPOT_EXPONENT,fSpotExponent);
- end;
- end;
- {**********************************************************}
- {**********************************************************}
- Constructor TLinkPoint.CreateSpecial(aWorldX,aWorldY,aWorldZ:Double);
- Begin
- Inherited Create;
- X:=aWorldX;
- Y:=aWorldy;
- Z:=aWorldZ;
- ScreenZ:=1;
- end;
- {**********************************************************}
- Procedure TLinkPoint.SetWorldPt(aX,aY,aZ:Double);
- Begin
- X:=aX;
- Y:=aY;
- z:=aZ;
- end;
- {**********************************************************}
- Function TLinkPoint.Duplicate:TLinkPoint;
- Begin
- Result:=TLinkPoint.Create;
- Result.X:=X;
- Result.Y:=Y;
- Result.Z:=Z;
- Result.sPt.X:=sPt.X;
- Result.sPt.Y:=sPt.Y;
- Result.sX:=sX;
- Result.sY:=sY;
- Result.ScreenZ:=ScreenZ;
- Result.fScreenPtValid:=fScreenPtValid;
- end;
- {**********************************************************}
- Function TLinkPoint.GetWorldPt :pGLDouble;
- Begin
- Result:=pGLDouble(@X);
- end;
- {**********************************************************}
- Procedure TLinkPoint.SetHeight(aHt:LongInt);
- Begin
- Spt.Y:=abs(SY-aHt);
- end;
- {**********************************************************}
- Function TLinkPoint.GetGLScreenPt(var aPt: TPoint):Boolean;
- Begin
- Result:=fScreenPtValid;
- If Not fScreenPtValid then exit;
- aPt.X:=aPt.X;
- aPt.Y:=aPt.Y;
- end;
- {**********************************************************}
- Procedure TLinkPoint.SetGLScreenPt(AX,AY,aHt:LongInt;AZ:Double);
- begin
- SX:=ax;
- SY:=ay;
- ScreenZ:=aZ;
- sPt.X:=aX;
- sPt.Y:=abs(ay-aHt);
- end;
- {**********************************************************}
- Procedure TLinkPoint.SetWinScreenPt(aX,aY,aHt:LongInt;aZ:Double);
- Begin
- SPt.X:=aX;
- SPt.Y:=aY;
- ScreenZ:=aZ;
- SX:=aX;
- SY:=aHt-AY;
- end;
- {**********************************************************}
- Procedure Scale_Data(
-
- Dmin, {data minimum}
- Dmax: Double; {data maximum}
- Nmax: Smallint; {max number of intervals}
- var st: Double; {starting value}
- var dinc: Double; {increment}
- var Ninc: SmallInt); {number of increments}
-
- { this routines calculates a nice starting value and increment such
- that the data is enclosed by the interval }
-
- Function LintVal( aval:Double ):Smallint;
-
- { this function returns the lower integer value between which a Double
- number lies. i.e. truncates if >0 and truncates-1 if <0 }
- var DL,DH:Smallint;
- begin
- DL:=Low(Smallint);
- DH:=High(Smallint);
- Result:=0;
- try
- if aval<0 then
- begin
- if (aval<DL) then REsult:=DL else REsult:=system.Trunc(aval)-1;
- end else
- Begin
- if (aval>DH) then REsult:=DH else REsult:=system.Trunc(aval);
- end;
- except
- On EInvalidOp do else Raise;
- end;
- end;
-
- Function PowerOf10( n:Smallint ):Double;
-
- { this function returns the nth power of 10 }
- var
- i: Smallint;
- aval: Double;
-
- begin
- aval:=1.0;
- Result:=aval;
- try
- if n>0 then for i:=1 to n do aval:=aval*10.0
- else if n<0 then for i:=1 to -n do aval:=aval/10.0;
- Result:=aval;
- except
- On EInvalidOp do else Raise;
- end;
- end;
-
- var
- OK: boolean;
- r,
- Range,
- En,v1,v2,v3: double;
- i,
- ipow: Smallint;
-
- Const
- Srange: array[1..80] of Double
- = (0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.11 ,0.12 ,0.12 ,0.125,
- 0.13 ,0.14 ,0.14 ,0.15 ,0.15 ,0.15 ,0.16 ,0.16 ,0.17 ,0.175,
- 0.18 ,0.18 ,0.19 ,0.2 ,0.2 ,0.2 ,0.2 ,0.2 ,0.2 ,0.22 ,
- 0.225,0.24 ,0.25 ,0.25 ,0.25 ,0.26 ,0.275,0.28 ,0.3 ,0.3 ,
- 0.3 ,0.3 ,0.32 ,0.325,0.34 ,0.35 ,0.35 ,0.36 ,0.375,0.38 ,
- 0.4 ,0.4 ,0.4 ,0.4 ,0.4 ,0.425,0.45 ,0.45 ,0.475,0.5 ,
- 0.5 ,0.5 ,0.5 ,0.5 ,0.55 ,0.6 ,0.6 ,0.6 ,0.65 ,0.7 ,
- 0.7 ,0.75 ,0.75 ,0.8 ,0.8 ,0.8 ,0.85 ,0.9 ,0.9 ,0.95 );
- Snum: array [1..80] of byte
- = (20 ,10 ,5 ,4 ,2 ,1 ,11 ,12 ,6 ,5 ,
- 13 ,14 ,7 ,15 ,6 ,3 ,16 ,8 ,17 ,7 ,
- 18 ,9 ,19 ,20 ,10 ,8 ,4 ,2 ,1 ,11 ,
- 9 ,12 ,10 ,5 ,1 ,13 ,11 ,14 ,15 ,12 ,
- 6 ,3 ,16 ,13 ,17 ,14 ,7 ,18 ,15 ,19 ,
- 20 ,16 ,8 ,4 ,2 ,17 ,18 ,9 ,19 ,20 ,
- 10 ,5 ,2 ,1 ,11 ,12 ,6 ,3 ,13 ,14 ,
- 7 ,15 ,3 ,16 ,8 ,4 ,17 ,18 ,9 ,19);
-
-
- begin
- { initial values}
- i:=0;
- OK:=false;
- st:=0;dinc:=0;Ninc:=0;
- Try
- { adjust invalid values for data items }
- if Nmax<1 then Nmax:=1;
- if Dmin>Dmax then begin
- r:=Dmin;
- Dmin:=Dmax;
- Dmax:=r;
- end;
- { bug fix if both equal 0 }
- if (Dmin=Dmax)and(Dmin=0.0) then begin
- st:=0.0;
- Ninc:=1;
- dinc:=1.0e-36;
- exit;
- end;
- { bug fix to prevent very small increments incomparison to value }
- if Dmax-Dmin<0.000001*Dmin then Dmax:=Dmin*1.000001;
-
- { calculate the range of the data and the order of magntiude }
- Range:=Abs(Dmax-Dmin);
- v1:=ln(Range);
- v2:=ln(10.0);
- v3:=V1/v2;
- ipow:=LintVal(v3);
- r:=Range/PowerOf10(ipow+1);
-
- { search for suitable range }
- repeat
-
- while (i<80)and(not OK) do begin
- i:=i+1;
- if (Srange[i]>=r*0.9999999)and(Snum[i]<=Nmax) then
- begin
- Ninc:=Snum[i];
- Dinc:=Srange[i]/Int(Ninc)*PowerOf10(ipow+1);
- V1:=DMin/Dinc+0.0000001;
- V2:=lintVal(V1);
- St:=v2*Dinc;
- En:=st+Int(Ninc)*Dinc;
- if (st<=Dmin+abs(Dmin)*0.0000001)and(En>=Dmax-abs(Dmax)*0.0000001) then OK:=true;
- end;
- end;
- if not OK then begin
- r:=r/10.0;
- ipow:=ipow+1;
- i:=0;
- end;
- until OK or (ipow>37);
-
- if not OK then begin
- Ninc:=1;
- Dinc:=range;
- st:=Dmin;
- end;
- except
- // fix for a very odd EInvalidOp at startup
- On EInvalidOp do else Raise;
- end;
- end;
- (***********************************************)
- Procedure CreateGrid(MinPt,MaxPt:tGLPoint;aGridType:GLGridType;aStep:LongInt);
-
- var MaxVal1,MinVal1,MaxVal2,MinVal2:double;
- Linestart,LineEnd :tGLPoint;
- StartVal,Inc:Double;
- NoInc,Step:Smallint;
-
- Procedure BottomTop(CommonVal:Double);
- var Count:LongInt;
- Begin
- MaxVal1:=MaxPt.X;MinVal1:=MinPt.X;
- maxVal2:=MaxPt.Y;MinVal2:=MinPt.Y;
- StartVal:=0;Inc:=0;NoInc:=0;
- //first series
- Scale_Data(MinVal1,MaxVal1,Step,StartVal,Inc,NoInc);
- Linestart.X:=StartVal;Linestart.Y:=MinPt.Y;Linestart.Z:=CommonVal;
- LineEnd.X:=StartVal;LineEnd.Y:=MaxPt.Y;LineEnd.Z:=CommonVal;
- GLBegin(GL_Lines);
- For Count:=0 to NoInc do
- Begin
- glVertex3dv(@LineStart);
- glvertex3dv(@LineEnd);
- LineStart.X:=LineStart.X+Inc;
- LineEnd.X:=LineEnd.X+inc;
- end;
- glEnd;
- //2nd series vary Y
- StartVal:=0;Inc:=0;NoInc:=0;
- Scale_Data(MinVal2,MaxVal2,Step,StartVal,Inc,NoInc);
- Linestart.X:=MinPt.X;Linestart.Y:=StartVal;Linestart.Z:=CommonVal;
- LineEnd.X:=MaxPt.X;LineEnd.Y:=StartVal;LineEnd.Z:=CommonVal;
- GLBegin(GL_Lines);
- For Count:=0 to NoInc do
- Begin
- glVertex3dv(@LineStart);
- glvertex3dv(@LineEnd);
- LineStart.Y:=LineStart.Y+Inc;
- LineEnd.Y:=LineEnd.Y+inc;
- end ;
- glEnd;
- end;
-
- Procedure LeftRight(CommonVal:Double);
- var Count:LongInt;
- Begin
- MaxVal1:=MaxPt.Z;MinVal1:=MinPt.Z;
- maxVal2:=MaxPt.Y;MinVal2:=MinPt.Y;
- //first series
- StartVal:=0;Inc:=0;NoInc:=0;
- Scale_Data(MinVal1,MaxVal1,Step,StartVal,Inc,NoInc);
- Linestart.X:=CommonVal;Linestart.Y:=MinPt.Y;Linestart.Z:=StartVal;
- LineEnd.X:=CommonVal;LineEnd.Y:=MaxPt.Y;LineEnd.Z:=StartVal;
- GLBegin(GL_Lines);
- For Count:=0 to NoInc do
- Begin
- glVertex3dv(@LineStart);
- glvertex3dv(@LineEnd);
- LineStart.Z:=LineStart.Z+Inc;
- LineEnd.Z:=LineEnd.Z+inc;
- end;
- glEnd;
- //2nd series vary Y
- StartVal:=0;Inc:=0;NoInc:=0;
- Scale_Data(MinVal2,MaxVal2,Step,StartVal,Inc,NoInc);
- Linestart.X:=CommonVal;Linestart.Y:=StartVal;Linestart.Z:=MinPt.Z;
- LineEnd.X:=CommonVal;LineEnd.Y:=StartVal;LineEnd.Z:=MaxPt.Z;
- GLBegin(GL_Lines);
- For Count:=0 to NoInc do
- Begin
- glVertex3dv(@LineStart);
- glvertex3dv(@LineEnd);
- LineStart.Y:=LineStart.Y+Inc;
- LineEnd.Y:=LineEnd.Y+inc;
- end;
- glEnd;
- end;
- Procedure FrontBack(CommonVal:Double);
- var Count:LongInt;
- Begin
- MaxVal1:=MaxPt.Z;MinVal1:=MinPt.Z;
- maxVal2:=MaxPt.X;MinVal2:=MinPt.X;
- StartVal:=0;Inc:=0;NoInc:=0;
- //first series
- Scale_Data(MinVal1,MaxVal1,Step,StartVal,Inc,NoInc);
- Linestart.X:=MinPt.X;Linestart.Y:=CommonVal;Linestart.Z:=StartVal;
- LineEnd.X:=MaxPt.X;LineEnd.Y:=CommonVal;LineEnd.Z:=StartVal;
- GLBegin(GL_Lines);
- For Count:=0 to NoInc do
- Begin
- glVertex3dv(@LineStart);
- glvertex3dv(@LineEnd);
- LineStart.Z:=LineStart.Z+Inc;
- LineEnd.Z:=LineEnd.Z+inc;
- end ;
- glEnd;
- //2nd series vary Y
- StartVal:=0;Inc:=0;NoInc:=0;
- Scale_Data(MinVal2,MaxVal2,Step,StartVal,Inc,NoInc);
- Linestart.X:=StartVal;Linestart.Y:=CommonVal;Linestart.Z:=MinPt.Z;
- LineEnd.X:=StartVal;LineEnd.Y:=CommonVal;LineEnd.Z:=MaxPt.Z;
- GLBegin(GL_Lines);
- For Count:=0 to NoInc do
- Begin
- glVertex3dv(@LineStart);
- glvertex3dv(@LineEnd);
- LineStart.X:=LineStart.X+Inc;
- LineEnd.X:=LineEnd.X+inc;
- end;
- glEnd;
- end;
- begin
- If astep<=0 then step:=7 else step:=aStep;
- // set up for the L state in display list
- //create the necessay lines
- glColor4fv(@glBlack);
- Case aGridtype of
- gtBottom:{XY Min}BottomTop(MinPt.Z);
- gtTop: {XY,Max} BottomTop(MaxPt.Z);
- gtLeftSide: LeftRight(MinPt.X);
- gtRightSide: LeftRight(MaxPt.X);
- gtBack: FrontBack(MaxPt.Y);
- gtFront: FrontBack(MinPt.Y);
- end;
- end;
- {==========================================================================}
-
- end.
-