<> <> <> <> <<>> DIRECTORY SVCastRays, SVCoordSys, SVRay, SVGraphics, Feedback, Imager, SVMatrix3d, SVPadGraphics, SVPreprocess3d, SV2d, SV3d, SVModelTypes, SVSceneTypes, SVCatScan; SVCatScanImpl: CEDAR PROGRAM IMPORTS SVCastRays, SVCoordSys, SVRay, SVGraphics, Feedback, SVMatrix3d, SVPadGraphics, SVPreprocess3d EXPORTS SVCatScan = BEGIN Camera: TYPE = SVModelTypes.Camera; Classification: TYPE = SVSceneTypes.Classification; CSGTree: TYPE = SVSceneTypes.CSGTree; CoordSystem: TYPE = SVModelTypes.CoordSystem; FrameBlock: TYPE = SVSceneTypes.FrameBlock; Matrix4by4: TYPE = SV3d.Matrix4by4; Plane: TYPE = SV3d.Plane; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Ray: TYPE = SVSceneTypes.Ray; Vector3d: TYPE = SV3d.Vector3d; CatScanScanLine: TYPE = REF CatScanScanLineObj; CatScanScanLineObj: TYPE = SVCatScan.CatScanScanLineObj; CatScan: TYPE = REF CatScanObj; CatScanObj: TYPE = SVCatScan.CatScanObj; CreateCatScan: PUBLIC PROC [maxScans: NAT, coordSys: CoordSystem, frame: FrameBlock, plane: NAT] RETURNS [catScan: CatScan] = { catScan _ NEW[CatScanObj[maxScans]]; catScan.coordSys _ coordSys; catScan.frame _ frame; catScan.plane _ plane; FOR i: NAT IN [0..maxScans) DO catScan[i] _ NEW[CatScanScanLineObj]; ENDLOOP; }; UpdateCatScan: PUBLIC PROC [catScan: CatScan, coordSys: CoordSystem, frame: FrameBlock, plane: NAT] = { catScan.coordSys _ coordSys; catScan.frame _ frame; catScan.plane _ plane; }; ChangeCatScanPlane: PUBLIC PROC [catScan: CatScan, plane: NAT] = { catScan.plane _ plane; }; AddScanLineToCatScan: PRIVATE PROC [scanLine: NAT, class: Classification, localBasePt: Point3d, localDirection: Vector3d, catScan: CatScan] RETURNS [modified: CatScan] = { FOR i: NAT IN [1..class.count] DO t: REAL; t _ class.params[i]; catScan[scanLine].hits[i][1] _ localBasePt[1] + t*localDirection[1]; catScan[scanLine].hits[i][2] _ localBasePt[2] + t*localDirection[2]; catScan[scanLine].hits[i][3] _ localBasePt[3] + t*localDirection[3]; catScan[scanLine].classifs[i] _ class.classifs[i]; ENDLOOP; catScan[scanLine].count _ class.count; catScan[scanLine].classifs[class.count+1] _ class.classifs[class.count+1]; RETURN[catScan]; }; RayTraceTheCatScan: PUBLIC PROC [catScan: CatScan, tree: CSGTree, camera: Camera] = { y, z: REAL; inc: REAL; block: FrameBlock _ catScan.frame; basePt, worldBasePt: Point3d; direction, worldDirection: Vector3d; ray: Ray; class: Classification; localWRTCamera, localWRTWorld: Matrix4by4; [] _ SVPreprocess3d.PreprocessForCatScan[tree, camera]; localWRTCamera _ SVCoordSys.WRTCamera[catScan.coordSys, camera.coordSys]; localWRTWorld _ SVCoordSys.WRTWorld[catScan.coordSys]; ray _ SVRay.GetRayFromPool[]; SELECT catScan.plane FROM 1 => { -- x = 0 plane. Start rays from hi Z. y _ block.loY; inc _ (block.hiY - block.loY) / (catScan.maxScans - 1.0); direction _ [0.0, 0.0, block.loZ - block.hiZ]; worldDirection _ SVMatrix3d.UpdateVectorEvenScaling[direction, localWRTWorld]; FOR i: NAT IN [0..catScan.maxScans) DO basePt _ [0.0, y, block.hiZ]; worldBasePt _ SVMatrix3d.Update[basePt, localWRTWorld]; SVRay.StuffWorldRay[ray, worldBasePt, worldDirection, camera]; class _ SVCastRays.RayCastBoundingSpheres[ray, tree.son]; catScan _ AddScanLineToCatScan[i, class, basePt, direction, catScan]; SVCastRays.ReturnClassToPool[class]; catScan[i].lineVal _ y; y _ y + inc; ENDLOOP; }; 2 => { -- y = 0 plane. Start rays from lo X. z _ block.loZ; inc _ (block.hiZ - block.loZ) / (catScan.maxScans - 1.0); direction _ [block.hiX - block.loX, 0.0, 0.0]; worldDirection _ SVMatrix3d.UpdateVectorEvenScaling[direction, localWRTWorld]; FOR i: NAT IN [0..catScan.maxScans) DO basePt _ [block.loX, 0.0, z]; worldBasePt _ SVMatrix3d.Update[basePt, localWRTWorld]; SVRay.StuffWorldRay[ray, worldBasePt, worldDirection, camera]; class _ SVCastRays.RayCastBoundingSpheres[ray, tree.son]; catScan _ AddScanLineToCatScan[i, class, basePt, direction, catScan]; SVCastRays.ReturnClassToPool[class]; catScan[i].lineVal _ z; z _ z + inc; ENDLOOP; }; 3 => { -- z = 0 plane. Start rays from lo X. y _ block.loY; inc _ (block.hiY - block.loY) / (catScan.maxScans - 1.0); direction _ [block.hiX - block.loX, 0.0, 0.0]; worldDirection _ SVMatrix3d.UpdateVectorEvenScaling[direction, localWRTWorld]; FOR i: NAT IN [0..catScan.maxScans) DO basePt _ [block.loX, y, 0.0]; worldBasePt _ SVMatrix3d.Update[basePt, localWRTWorld]; SVRay.StuffWorldRay[ray, worldBasePt, worldDirection, camera]; class _ SVCastRays.RayCastBoundingSpheres[ray, tree.son]; catScan _ AddScanLineToCatScan[i, class, basePt, direction, catScan]; SVCastRays.ReturnClassToPool[class]; catScan[i].lineVal _ y; y _ y + inc; ENDLOOP; }; ENDCASE => ERROR Feedback.Problem["All three is not yet implemented"]; SVRay.ReturnRayToPool[ray]; ClipCatScanAgainstFrame[catScan]; }; WidthAndHeight: PUBLIC PROC [catScan: CatScan] RETURNS [width, height: REAL] = { f: FrameBlock _ catScan.frame; SELECT catScan.plane FROM 1 => { -- x = 0 plane. y top to bottom. z left to right. width _ f.hiZ - f.loZ; height _ f.hiY - f.loY; }; 2 => { -- y = 0 plane. z top to bottom. x left to right. width _ f.hiX - f.loX; height _ f.hiZ - f.loZ; }; 3, 4 => { -- z = 0 plane. y top to bottom. x left to right. width _ f.hiX - f.loX; height _ f.hiY - f.loY; }; ENDCASE => ERROR; }; ShiftScanLineUp: PRIVATE PROC [catScan: CatScan, i: NAT] = { FOR j: NAT _ catScan[i].count, j-1 UNTIL j < 1 DO catScan[i].hits[j+1] _ catScan[i].hits[j]; catScan[i].classifs[j+1] _ catScan[i].classifs[j]; ENDLOOP; }; ClipCatScanAgainstFrame: PRIVATE PROC [catScan: CatScan] = { <> startPt, endPt: Point3d; block: FrameBlock _ catScan.frame; beenIn: BOOL; SELECT catScan.plane FROM 1 => { FOR i: NAT IN [0..catScan.maxScans) DO <> beenIn _ FALSE; startPt _ [0, catScan[i].lineVal, block.hiZ]; <> IF catScan[i].classifs[1] = TRUE THEN { -- ray starts inside beenIn _ TRUE; ShiftScanLineUp[catScan, i]; catScan[i].hits[1] _ startPt; catScan[i].classifs[1] _ FALSE; catScan[i].count _ catScan[i].count + 1; }; FOR j: NAT IN [1..catScan[i].count] DO endPt _ catScan[i].hits[j]; IF endPt[3] > block.loZ AND endPt[3] < block.hiZ THEN beenIn _ TRUE; IF endPt[3] < block.loZ THEN GOTO EndOfScanline; REPEAT EndOfScanline => { -- use this point instead of the out of bounds one IF beenIn THEN { catScan[i].hits[j] _ [0, catScan[i].lineVal, block.loZ]; catScan[i].count _ j; } ELSE catScan[i].count _ 0; }; FINISHED => { IF beenIn THEN { IF catScan[i].classifs[catScan[i].count + 1] = TRUE THEN { catScan[i].count _ catScan[i].count + 1; catScan[i].hits[catScan[i].count] _ [0, catScan[i].lineVal, block.loZ]; }; } ELSE catScan[i].count _ 0; }; ENDLOOP; ENDLOOP; }; 2 => { FOR i: NAT IN [0..catScan.maxScans) DO <> beenIn _ FALSE; startPt _ [block.loX, 0, catScan[i].lineVal]; <> IF catScan[i].classifs[1] = TRUE THEN { beenIn _ TRUE; ShiftScanLineUp[catScan, i]; catScan[i].hits[1] _ startPt; catScan[i].classifs[1] _ FALSE; catScan[i].count _ catScan[i].count + 1; }; FOR j: NAT IN [1..catScan[i].count] DO endPt _ catScan[i].hits[j]; IF endPt[1] < block.hiX AND endPt[1] > block.loX THEN beenIn _ TRUE; IF endPt[1] > block.hiX THEN GOTO EndOfScanline; REPEAT EndOfScanline => { IF beenIn THEN { catScan[i].hits[j] _ [block.hiX, 0, catScan[i].lineVal]; catScan[i].count _ j; } ELSE catScan[i].count _ 0; }; FINISHED => { IF beenIn THEN { IF catScan[i].classifs[catScan[i].count + 1] = TRUE THEN { catScan[i].count _ catScan[i].count + 1; catScan[i].hits[catScan[i].count] _ [block.hiX, 0, catScan[i].lineVal]; }; } ELSE catScan[i].count _ 0; }; ENDLOOP; ENDLOOP; }; 3 => { FOR i: NAT IN [0..catScan.maxScans) DO <> beenIn _ FALSE; startPt _ [block.loX, catScan[i].lineVal, 0]; <> IF catScan[i].classifs[1] = TRUE THEN { beenIn _ TRUE; ShiftScanLineUp[catScan, i]; catScan[i].hits[1] _ startPt; catScan[i].classifs[1] _ FALSE; catScan[i].count _ catScan[i].count + 1; }; FOR j: NAT IN [1..catScan[i].count] DO endPt _ catScan[i].hits[j]; IF endPt[1] < block.hiX AND endPt[1] > block.loX THEN beenIn _ TRUE; IF endPt[1] > block.hiX THEN GOTO EndOfScanline; REPEAT EndOfScanline => { IF beenIn THEN { catScan[i].hits[j] _ [block.hiX, catScan[i].lineVal, 0]; catScan[i].count _ j; } ELSE catScan[i].count _ 0; }; FINISHED => { IF beenIn THEN { IF catScan[i].classifs[catScan[i].count + 1] = TRUE THEN { catScan[i].count _ catScan[i].count + 1; catScan[i].hits[catScan[i].count] _ [block.hiX, catScan[i].lineVal, 0]; }; } ELSE catScan[i].count _ 0; }; ENDLOOP; ENDLOOP; }; ENDCASE => ERROR; }; DrawCatScan: PUBLIC PROC [dc: Imager.Context, catScan: CatScan, origin: Point2d] = TRUSTED { <> <> startPtLocal, endPtLocal: Point3d; startPad, endPad: Point2d; SELECT catScan.plane FROM 1 => { -- x=0 plane FOR i: NAT IN [0..catScan.maxScans) DO <> FOR j: NAT IN [2..catScan[i].count] DO <> IF catScan[i].classifs[j] THEN { startPtLocal _ catScan[i].hits[j-1]; endPtLocal _ catScan[i].hits[j]; startPad _ [-startPtLocal[3], startPtLocal[2]]; endPad _ [-endPtLocal[3], endPtLocal[2]]; SVPadGraphics.MoveTo[dc, startPad, origin]; SVPadGraphics.DrawTo[dc, endPad, origin]; }; ENDLOOP; ENDLOOP; }; 2 => { -- y = 0 plane FOR i: NAT IN [0..catScan.maxScans) DO <> FOR j: NAT IN [2..catScan[i].count] DO <> IF catScan[i].classifs[j] THEN { startPtLocal _ catScan[i].hits[j-1]; endPtLocal _ catScan[i].hits[j]; startPad _ [startPtLocal[1], -startPtLocal[3]]; endPad _ [endPtLocal[1], -endPtLocal[3]]; SVPadGraphics.MoveTo[dc, startPad, origin]; SVPadGraphics.DrawTo[dc, endPad, origin]; }; ENDLOOP; ENDLOOP; }; 3, 4 => { FOR i: NAT IN [0..catScan.maxScans) DO <> FOR j: NAT IN [2..catScan[i].count] DO <> IF catScan[i].classifs[j] THEN { startPtLocal _ catScan[i].hits[j-1]; endPtLocal _ catScan[i].hits[j]; startPad _ [startPtLocal[1], startPtLocal[2]]; endPad _ [endPtLocal[1], endPtLocal[2]]; SVPadGraphics.MoveTo[dc, startPad, origin]; SVPadGraphics.DrawTo[dc, endPad, origin]; }; ENDLOOP; ENDLOOP; }; ENDCASE => ERROR; }; <> <> <> <> <> <> < catScan[i].count DO>> <> <> <> <> <> <> <> <> <<};>> <<>> <<>> DrawCatScan3d: PUBLIC PROC [dc: Imager.Context, catScan: CatScan, camera: Camera] = TRUSTED { <> startPtLocal, endPtLocal: Point3d; FOR i: NAT IN [0..catScan.maxScans) DO FOR j: NAT IN [2..catScan[i].count] DO IF catScan[i].classifs[j] THEN { startPtLocal _ catScan[i].hits[j-1]; endPtLocal _ catScan[i].hits[j]; SVGraphics.DrawLine[dc, startPtLocal, endPtLocal, camera, catScan.coordSys]; }; ENDLOOP; ENDLOOP; }; END.