<> <> <> <> <<>> DIRECTORY AtomButtonsTypes, CoordSys, Feedback, FunctionCache, Imager, ImagerColor, ImagerColorPrivate, Matrix3d, PriorityQueue, Real, Rope, SV2d, SV3d, SVArtwork, SVAssembly, SVBasicTypes, SVBoundBox, SVMatrixOps, SVModelTypes, SVScene, SVSceneTypes, SVToolObject, SVTransforms, SVUtility, ViewerClasses; SVAssemblyImpl: CEDAR PROGRAM IMPORTS CoordSys, Feedback, FunctionCache, Imager, ImagerColor, ImagerColorPrivate, Matrix3d, PriorityQueue, Rope, SVArtwork, SVBoundBox, SVMatrixOps, SVScene, SVToolObject, SVTransforms, SVUtility EXPORTS SVAssembly = BEGIN Artwork: TYPE = SVModelTypes.Artwork; Slice: TYPE = SVSceneTypes.Slice; SliceList: TYPE = SVSceneTypes.SliceList; SliceListObj: TYPE = SVSceneTypes.SliceListObj; SliceObj: TYPE = SVSceneTypes.SliceObj; BoundBox: TYPE = SVBasicTypes.BoundBox; BoundHedron: TYPE = SVBasicTypes.BoundHedron; Camera: TYPE = SVModelTypes.Camera; Color: TYPE = Imager.Color; CoordSystem: TYPE = SVModelTypes.CoordSystem; FeedbackData: TYPE = AtomButtonsTypes.FeedbackData; LightSourceList: TYPE = SVSceneTypes.LightSourceList; Line3d: TYPE = SV3d.Line3d; MasterObject: TYPE = SVSceneTypes.MasterObject; Matrix4by4: TYPE = SV3d.Matrix4by4; PlanarSurface: TYPE = SVSceneTypes.PlanarSurface; PlanarSurfaceList: TYPE = SVSceneTypes.PlanarSurfaceList; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; PointAndDone: TYPE = SVSceneTypes.PointAndDone; PointPairAndDone: TYPE = SVSceneTypes.PointPairAndDone; PointGenerator: TYPE = SVSceneTypes.PointGenerator; PointPairGenerator: TYPE = SVSceneTypes.PointPairGenerator; PointSetOp: TYPE = SVSceneTypes.PointSetOp; -- {union, intersection, difference} Scene: TYPE = SVSceneTypes.Scene; SelectionClass: TYPE = SVSceneTypes.SelectionClass; SelectMode: TYPE = SVSceneTypes.SelectMode; Shape: TYPE = SVSceneTypes.Shape; ShapeObj: TYPE = SVSceneTypes.ShapeObj; ShowAsType: TYPE = SVSceneTypes.ShowAsType; SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor; SliceDescriptorObj: TYPE = SVSceneTypes.SliceDescriptorObj; SliceParts: TYPE = SVSceneTypes.SliceParts; ToolData: TYPE = SVSceneTypes.ToolData; Vector3d: TYPE = SV3d.Vector3d; Viewer: TYPE = ViewerClasses.Viewer; Problem: SIGNAL [msg: Rope.ROPE] = Feedback.Problem; bBoxCacheSize: NAT = 3; CreatePrimitive: PUBLIC PROC [name: Rope.ROPE, object: Rope.ROPE, scene: Scene, artwork: Artwork _ NIL, isTool: BOOL _ FALSE, toolData: ToolData _ NIL] RETURNS [prim: Slice, masterObjectFound: BOOL, success: BOOL] = { masterObject: MasterObject; toolMasterObject: MasterObject; shape: Shape; toolName: Rope.ROPE; BEGIN success _ TRUE; IF SVScene.AssemblyNameIsPresent[name, scene] THEN GOTO NameAlreadyPresent; IF toolData = NIL THEN toolMasterObject _ NIL ELSE { toolName _ CoordSys.NameWithSuffix[name, "$$tool", scene.coordSysRoot]; toolMasterObject _ SVToolObject.ToolMakeMasterObject[toolName, toolData]; }; [masterObject, masterObjectFound] _ SVScene.FindObjectFromName[object, scene]; IF NOT masterObjectFound THEN RETURN; IF artwork = NIL THEN artwork _ SVArtwork.CreateColorArtwork[ImagerColor.ColorFromRGB[[.6,.6,.8]], plastic]; -- light blue shape _ NEW[ShapeObj]; shape.mo _ masterObject; <<>> <> prim _ NEW[SliceObj _ [ name: name, coordSys: NIL, shape: shape, bBoxCache: FunctionCache.Create[maxEntries: bBoxCacheSize], artwork: artwork, showAs: normal, isTool: isTool, toolMasterObject: toolMasterObject ]]; EXITS NameAlreadyPresent => { Feedback.AppendRaw[$Solidviews, Rope.Cat["Slice ", name, " already present."], oneLiner]; Feedback.BlinkRaw[$Solidviews]; RETURN[NIL, TRUE, FALSE]; }; END; }; <> <> <> <<>> AddPrimitive: PUBLIC PROC [prim: Slice, size: Vector3d, parent: Slice, mat: Matrix4by4, scene: Scene] RETURNS [success: BOOL] = { <> scalarName: Rope.ROPE; shape: Shape; IF ISTYPE[parent.shape, SliceList] THEN { -- add to old SliceList alist: SliceList _ NARROW[parent.shape]; cs: CoordSystem; scalarCS: CoordSystem; cs _ CoordSys.CreateCoordSysInTree[prim.name, mat, parent.coordSys, scene.coordSysRoot !CoordSys.NameAlreadyExists => ERROR]; prim.coordSys _ cs; scalarName _ CoordSys.NameWithSuffix[prim.name, "$$Scalars", scene.coordSysRoot]; scalarCS _ CoordSys.CreateScalarsOnlyCoordSysInTree[scalarName, size, cs, scene.coordSysRoot !CoordSys.NameAlreadyExists => ERROR]; shape _ NARROW[prim.shape]; shape.coordSys _ scalarCS; parent.shape _ SVUtility.AppendToAssemblyList[prim, alist]; success _ TRUE; } ELSE { Feedback.AppendRaw[$Solidviews, "Attempt to add subassembly to primitive.", oneLiner]; Feedback.BlinkRaw[$Solidviews]; RETURN[FALSE]; }; }; <<>> CreatePrimitiveAtExistingCoordSys: PUBLIC PROC [name: Rope.ROPE, object: Rope.ROPE, size: Vector3d, scene: Scene, coordSys: CoordSystem, artwork: Artwork _ NIL, isTool: BOOL _ FALSE, toolData: ToolData _ NIL] RETURNS [assembly: Slice, masterObjectFound: BOOL] = { masterObject: MasterObject; toolMasterObject: MasterObject; shape: Shape; scalarCS: CoordSystem; toolName, scalarName: Rope.ROPE; IF toolData = NIL THEN toolMasterObject _ NIL ELSE { toolName _ CoordSys.NameWithSuffix[name, "$$tool", scene.coordSysRoot]; toolMasterObject _ SVToolObject.ToolMakeMasterObject[toolName, toolData]; }; [masterObject, masterObjectFound] _ SVScene.FindObjectFromName[object, scene]; IF NOT masterObjectFound THEN { Feedback.AppendRaw[$Solidviews, Rope.Cat["Couldn't add assembly ", name, ". Master object ", object, " not found."], oneLiner]; Feedback.BlinkRaw[$Solidviews]; }; IF artwork = NIL THEN artwork _ SVArtwork.CreateColorArtwork[ImagerColor.ColorFromRGB[[.6,.6,.8]], plastic]; -- light blue shape _ NEW[ShapeObj]; shape.mo _ masterObject; <> assembly _ NEW[SliceObj _ [ name: name, coordSys: NIL, shape: shape, bBoxCache: FunctionCache.Create[maxEntries: bBoxCacheSize], artwork: artwork, showAs: normal, isTool: isTool, toolMasterObject: toolMasterObject ]]; <> assembly.coordSys _ coordSys; scalarName _ CoordSys.NameWithSuffix[assembly.name, "$$Scalars", scene.coordSysRoot]; scalarCS _ CoordSys.CreateScalarsOnlyCoordSysInTree[scalarName, size, coordSys, scene.coordSysRoot]; shape.coordSys _ scalarCS; }; CreateCluster: PUBLIC PROC [name: Rope.ROPE, pointSetOp: PointSetOp _ union, scene: Scene, isTool: BOOL _ FALSE, toolData: ToolData _ NIL] RETURNS [assembly: Slice, success: BOOL] = { <> artwork: Artwork _ SVArtwork.CreateColorArtwork[Imager.white, plastic]; -- white toolMasterObject: MasterObject; toolName: Rope.ROPE; BEGIN success _ TRUE; IF SVScene.AssemblyNameIsPresent[name, scene] THEN GOTO NameInUse; IF toolData = NIL THEN toolMasterObject _ NIL ELSE { toolName _ CoordSys.NameWithSuffix[name, "$$tool", scene.coordSysRoot]; toolMasterObject _ SVToolObject.ToolMakeMasterObject[toolName, toolData]; }; assembly _ NEW[SliceObj _ [ name: name, coordSys: NIL, shape: NEW[SliceListObj _ [NIL, pointSetOp]], bBoxCache: FunctionCache.Create[maxEntries: bBoxCacheSize], artwork: artwork, showAs: normal, isTool: isTool, toolMasterObject: toolMasterObject ]]; EXITS NameInUse => { Feedback.AppendRaw[$Solidviews, Rope.Cat["Composite name ", name, " is already registered. Try another."], oneLiner]; Feedback.BlinkRaw[$Solidviews]; RETURN[NIL, FALSE]; }; END; }; AddCluster: PUBLIC PROC [cluster: Slice, parent: Slice, mat: Matrix4by4, scene: Scene] RETURNS [success: BOOL] = { <> IF IsComposite[parent] THEN{ -- add to old SliceList alist: SliceList _ NARROW[parent.shape]; cluster.coordSys _ CoordSys.CreateCoordSysInTree[cluster.name, mat, parent.coordSys, scene.coordSysRoot]; parent.shape _ SVUtility.AppendToAssemblyList[cluster, alist]; } ELSE { Feedback.AppendRaw[$Solidviews, "Attempt to add subassembly to primitive.", oneLiner]; Feedback.BlinkRaw[$Solidviews]; RETURN[FALSE]; }; }; CreateClusterAssemblyAtExistingCoordSys: PUBLIC PROC [name: Rope.ROPE, pointSetOp: PointSetOp, scene: Scene, coordSys: CoordSystem, isTool: BOOL _ FALSE, toolData: ToolData _ NIL] RETURNS [assembly: Slice] = { artwork: Artwork _ SVArtwork.CreateColorArtwork[Imager.white, plastic]; -- white toolMasterObject: MasterObject; toolName: Rope.ROPE; IF toolData = NIL THEN toolMasterObject _ NIL ELSE { toolName _ CoordSys.NameWithSuffix[name, "$$tool", scene.coordSysRoot]; toolMasterObject _ SVToolObject.ToolMakeMasterObject[toolName, toolData]; }; assembly _ NEW[SliceObj _ [ name: name, coordSys: NIL, shape: NEW[SliceListObj _ [NIL, pointSetOp]], bBoxCache: FunctionCache.Create[maxEntries: bBoxCacheSize], artwork: artwork, showAs: normal, isTool: isTool, toolMasterObject: toolMasterObject ]]; assembly.coordSys _ coordSys; }; AttemptToAddSubassemblyToPrimitive: PUBLIC SIGNAL = CODE; ConnectAssemblyToParent: PUBLIC PROC [assembly: Slice, parent: Slice] = { IF IsComposite[parent] THEN { -- add to old SliceList alist: SliceList _ NARROW[parent.shape]; parent.shape _ SVUtility.AppendToAssemblyList[assembly, alist]; } ELSE SIGNAL AttemptToAddSubassemblyToPrimitive; }; <> IsComposite: PUBLIC PROC [assem: Slice] RETURNS [BOOL] = { RETURN[ISTYPE [assem.shape, SliceList] OR assem.shape = NIL]; }; <> GetHedron: PUBLIC PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = { <> hedron _ mo.class.getHedron[mo]; }; BoundBoxEntry: TYPE = REF BoundBoxEntryObj; BoundBoxEntryObj: TYPE = RECORD [ bBox: BoundBox, ok: BOOL _ FALSE ]; GetBoundBox: PUBLIC PROC [assem: Slice, parts: SliceParts, camera: Camera] RETURNS [bBox: BoundBox] = { CompareEntries2: PROC [argument: FunctionCache.Domain] RETURNS [good: BOOL] = { thisName: Rope.ROPE _ NARROW[argument]; good _ Rope.Equal[thisName, camera.viewName, FALSE]; }; bBoxCache: FunctionCache.Cache _ assem.bBoxCache; oldEntryAny: REF ANY; oldEntry: BoundBoxEntry; ok: BOOL; BEGIN [oldEntryAny, ok] _ FunctionCache.Lookup[bBoxCache, CompareEntries2]; IF NOT ok THEN GOTO UpdateTheCache -- not in cache ELSE { oldEntry _ NARROW[oldEntryAny]; IF NOT oldEntry.ok THEN GOTO UpdateTheCache -- cache out of date ELSE bBox _ oldEntry.bBox; }; EXITS UpdateTheCache => { UpdateBoundBoxForCamera[assem, camera]; bBox _ GetBoundBox[assem, parts, camera]; -- recursive call }; END; }; UpdateBoundBoxForCamera: PUBLIC PROC [assem: Slice, camera: Camera] = { <> CompareEntries: PROC [argument: FunctionCache.Domain] RETURNS [good: BOOL] = { thisName: Rope.ROPE _ NARROW[argument]; good _ Rope.Equal[thisName, camera.viewName, FALSE]; }; bBoxCache: FunctionCache.Cache _ assem.bBoxCache; oldEntryAny: REF ANY; oldEntry: BoundBoxEntry; ok: BOOL _ FALSE; [oldEntryAny, ok] _ FunctionCache.Lookup[bBoxCache, CompareEntries]; IF ok THEN { oldEntry _ NARROW[oldEntryAny]; FillBox[oldEntry.bBox, assem, camera]; oldEntry.ok _ TRUE; } ELSE { newEntry: BoundBoxEntry _ NEW[BoundBoxEntryObj]; newEntry.bBox _ SVBoundBox.NullBoundBox[]; FillBox[newEntry.bBox, assem, camera]; newEntry.ok _ TRUE; FunctionCache.Insert[bBoxCache, camera.viewName, newEntry, 0]; }; }; FillBox: PROC [bBox: BoundBox, slice: Slice, camera: Camera] = { shape: Shape _ NARROW[slice.shape]; hedron: BoundHedron; mo: MasterObject _ shape.mo; hedron _ GetHedron[mo]; SVBoundBox.FillBoundBoxFromBoundHedron[hedron, camera, shape.coordSys, bBox]; EnlargeByOffset[bBox, 2.0]; -- allow for stroke width }; EnlargeByOffset: PROC [bBox: BoundBox, offset: REAL] = { IF bBox.null OR bBox.infinite THEN RETURN; bBox.loX _ bBox.loX - offset; bBox.hiX _ bBox.hiX + offset; bBox.loY _ bBox.loY - offset; bBox.hiY _ bBox.hiY + offset; }; UpdateBoundBoxes: PROC [slice: Slice, cameraList: LIST OF Camera _ NIL] = { <> oldEntry: BoundBoxEntry; bBoxCache: FunctionCache.Cache _ slice.bBoxCache; allCache: LIST OF FunctionCache.CacheEntry _ FunctionCache.GetList[bBoxCache]; FOR list: LIST OF FunctionCache.CacheEntry _ allCache, list.rest UNTIL list = NIL DO oldEntry _ NARROW[list.first.value]; IF oldEntry # NIL THEN oldEntry.ok _ FALSE; ENDLOOP; FOR list: LIST OF Camera _ cameraList, list.rest UNTIL list = NIL DO UpdateBoundBoxForCamera[slice, list.first]; ENDLOOP; }; <<>> <> DrawTransform: PUBLIC PROC [sliceD: SliceDescriptor, dc: Imager.Context, scene: Scene, camera: Camera, transform: Matrix4by4] = { SELECT camera.style FROM wire => DrawWireAssemblyTransform[sliceD, dc, camera, transform]; shaded => ERROR; -- use AddPolygonsToBufferTransform normals => { assem: Slice _ sliceD.slice; oldAssemblyWORLD: Matrix4by4 _ CoordSys.WRTWorld[assem.coordSys]; newAssemblyWORLD: Matrix4by4 _ Matrix3d.Mult[oldAssemblyWORLD, transform]; AbsTransf[assem, scene, newAssemblyWORLD]; DrawNormalsAssembly[dc, assem, scene, camera]; AbsTransf[assem, scene, oldAssemblyWORLD]; }; ENDCASE => SIGNAL NotYetImplemented; }; DeeperPlanarPolygon: PROC [x,y: PriorityQueue.Item, data: REF _ NIL] RETURNS [BOOL] = { xS: PlanarSurface _ NARROW[x]; yS: PlanarSurface _ NARROW[y]; RETURN[xS.depth < yS.depth]; }; DrawParts: PUBLIC PROC [slice: Slice, parts: SliceParts _ NIL, dc: Imager.Context, scene: Scene, camera: Camera, quick: BOOL] = { IF parts = NIL THEN Draw[slice, dc, scene, camera]; }; Draw: PUBLIC PROC [assem: Slice, dc: Imager.Context, scene: Scene, camera: Camera] = { sliceD: SliceDescriptor _ NewParts[assem, NIL, [0,0,0], slice]; DrawTransform[sliceD, dc, scene, camera, Matrix3d.Identity[]]; }; DrawWireAssembly: PROC [assembly: Slice, dc: Imager.Context, camera: Camera] = { SetColor[dc, camera, Imager.black]; SELECT assembly.showAs FROM tool => { toolMasterObject: MasterObject _ assembly.toolMasterObject; IF toolMasterObject = NIL THEN { Feedback.AppendTypescriptRaw[$Solidviews, Rope.Cat["Slice ", assembly.name, " is a tool but has no tool data. Contact implementor."], oneLiner]; RETURN; }; toolMasterObject.class.lineDraw[assembly, dc, camera]; }; normal => { WITH assembly.shape SELECT FROM assems: SliceList => { FOR subassemblies: LIST OF Slice _ assems.list, subassemblies.rest UNTIL subassemblies = NIL DO DrawWireAssembly[subassemblies.first, dc, camera]; ENDLOOP; }; shape: Shape => { shape.mo.class.lineDraw[assembly, dc, camera]; }; ENDCASE => ERROR; }; invisible => {}; both => ERROR Feedback.Problem[msg: "Can't have both"]; ENDCASE => ERROR; }; DrawWireAssemblyTransform: PROC [sliceD: SliceDescriptor, dc: Imager.Context, camera: Camera, transform: Matrix4by4] = { assembly: Slice _ sliceD.slice; SetColor[dc, camera, Imager.black]; SELECT assembly.showAs FROM normal => { WITH assembly.shape SELECT FROM assems: SliceList => { SIGNAL Problem[msg: "LineDraw not implemented for composite assemblies"]; }; shape: Shape => { shape.mo.class.lineDrawTransform[sliceD, dc, camera, transform]; }; ENDCASE => ERROR; }; invisible, tool => {}; both => ERROR Feedback.Problem[msg: "Can't have both"]; ENDCASE => ERROR; }; AddPolygonsToBuffer: PUBLIC PROC [surfaceQueue: PriorityQueue.Ref, assembly: Slice, camera: Camera] = { PutAssemblyOnQueue[assembly, surfaceQueue, camera.coordSys]; }; AddPolygonsToBufferTransform: PUBLIC PROC [surfaceQueue: PriorityQueue.Ref, sliceD: SliceDescriptor, scene: Scene, camera: Camera, transform: Matrix4by4] = { PutAssemblyOnQueueTransform[sliceD, surfaceQueue, camera.coordSys, transform]; }; DrawBuffer: PUBLIC PROC [dc: Imager.Context, surfaceQueue: PriorityQueue.Ref, scene: Scene, camera: Camera] = { DoDrawBuffer: PROC = { thisPlanarSurf: PlanarSurface; mo: MasterObject; FOR i: INT IN[1..PriorityQueue.Size[surfaceQueue]] DO thisPlanarSurf _ NARROW[PriorityQueue.Remove[surfaceQueue]]; mo _ thisPlanarSurf.mo; mo.class.drawSurf[dc, thisPlanarSurf, scene.lightSources, camera]; ENDLOOP; }; Imager.DoSaveAll[dc, DoDrawBuffer]; }; DrawNormalsAssembly: PROC [dc: Imager.Context, assembly: Slice, scene: Scene, camera: Camera] = { lightSources: LightSourceList _ scene.lightSources; SetColor[dc, camera, Imager.black]; WITH assembly.shape SELECT FROM assems: SliceList => { FOR subassemblies: LIST OF Slice _ assems.list, subassemblies.rest UNTIL subassemblies = NIL DO DrawNormalsAssembly[dc, subassemblies.first, scene, camera]; ENDLOOP; }; shape: Shape => { shape.mo.class.normalsDraw[dc, shape.mo.shadeBody, camera, shape.coordSys]; }; ENDCASE => ERROR; }; DrawSelectionFeedback: PUBLIC PROC [slice: Slice, selectedParts: SliceParts, hotParts: SliceParts, dc: Imager.Context, camera: Camera, dragInProgress, caretIsMoving, hideHot, quick: BOOL] = { shape: Shape _ NARROW[slice.shape]; mo: MasterObject _ shape.mo; mo.class.drawSelectionFeedback[slice, selectedParts, hotParts, dc, camera, dragInProgress, caretIsMoving, hideHot, quick]; }; DrawAttractorFeedback: PUBLIC PROC [sliceD: SliceDescriptor, selectedParts: SliceParts, dragInProgress: BOOL, dc: Imager.Context, camera: Camera] = { shape: Shape _ NARROW[sliceD.slice.shape]; mo: MasterObject _ shape.mo; mo.class.drawAttractorFeedback[sliceD, selectedParts, dragInProgress, dc, camera]; }; CountSurfacesInAssembly: PROC [assembly: Slice] RETURNS [surfCount: NAT] = { WITH assembly.shape SELECT FROM assems: SliceList => surfCount _ CountSurfacesInAssemblyList[assems]; shape: Shape => surfCount _ shape.mo.class.countSurf[shape.mo]; ENDCASE => ERROR; }; CountSurfacesInAssemblyList: PROC [asl: SliceList] RETURNS [surfCount: NAT] = { surfCount _ 0; FOR list: LIST OF Slice _ asl.list, list.rest UNTIL list = NIL DO surfCount _ surfCount + CountSurfacesInAssembly[list.first]; ENDLOOP; }; PutAssemblyOnQueue: PROC [assembly: Slice, q: PriorityQueue.Ref, cameraCS: CoordSystem] = { thisSurf: PlanarSurface; cameraNormal: Vector3d; surfList: PlanarSurfaceList; SELECT assembly.showAs FROM tool => { toolMasterObject: MasterObject _ assembly.toolMasterObject; surfList _ toolMasterObject.class.getSurf[assembly, cameraCS]; FOR surfList _ surfList, surfList.rest UNTIL surfList = NIL DO thisSurf _ surfList.first; cameraNormal _ Matrix3d.UpdateVectorWithInverse[CoordSys.FindCameraInTermsOf[assembly.coordSys, cameraCS], thisSurf.normal]; thisSurf.normal _ cameraNormal; PriorityQueue.Insert[q, thisSurf]; ENDLOOP; }; normal => { WITH assembly.shape SELECT FROM assems: SliceList => { FOR list: LIST OF Slice _ assems.list, list.rest UNTIL list = NIL DO PutAssemblyOnQueue[list.first, q, cameraCS]; ENDLOOP; }; shape: Shape => { cameraShape: Matrix4by4; cameraShape _ CoordSys.FindCameraInTermsOf[shape.coordSys, cameraCS]; surfList _ shape.mo.class.getSurf[assembly, cameraCS]; FOR surfList _ surfList, surfList.rest UNTIL surfList = NIL DO thisSurf _ surfList.first; cameraNormal _ Matrix3d.UpdateVectorWithInverse[cameraShape, thisSurf.normal]; thisSurf.normal _ cameraNormal; <> IF thisSurf.normal[3] >0 THEN PriorityQueue.Insert[q,thisSurf]; ENDLOOP; }; ENDCASE => ERROR; }; invisible => {}; both => ERROR Feedback.Problem[msg: "Can't have both."]; ENDCASE => ERROR; }; -- end of PutAssemblyOnQueue PutAssemblyOnQueueTransform: PROC [sliceD: SliceDescriptor, q: PriorityQueue.Ref, cameraCS: CoordSystem, transform: Matrix4by4] = { thisSurf: PlanarSurface; cameraNormal: Vector3d; surfList: PlanarSurfaceList; assembly: Slice _ sliceD.slice; SELECT assembly.showAs FROM tool => {}; normal => { WITH assembly.shape SELECT FROM assems: SliceList => { FOR list: LIST OF Slice _ assems.list, list.rest UNTIL list = NIL DO PutAssemblyOnQueue[list.first, q, cameraCS]; ENDLOOP; }; shape: Shape => { cameraShape: Matrix4by4; <> <> <> <> cameraShape _ CoordSys.FindCameraInTermsOf[shape.coordSys, cameraCS]; surfList _ shape.mo.class.getSurfTransform[sliceD, cameraCS, transform]; FOR surfList _ surfList, surfList.rest UNTIL surfList = NIL DO thisSurf _ surfList.first; cameraNormal _ Matrix3d.UpdateVectorWithInverse[cameraShape, thisSurf.normal]; thisSurf.normal _ cameraNormal; <> IF thisSurf.normal[3] >0 THEN PriorityQueue.Insert[q,thisSurf]; ENDLOOP; }; ENDCASE => ERROR; }; invisible => {}; both => ERROR Feedback.Problem[msg: "Can't have both."]; ENDCASE => ERROR; }; -- end of PutAssemblyOnQueue SetColor: PROC [dc: Imager.Context, camera: Camera, color: Color] = { IF camera.colorFilm THEN Imager.SetColor[dc, color] ELSE { intensity: REAL _ ImagerColorPrivate.IntensityFromColor[NARROW[color]]; Imager.SetColor[dc, ImagerColor.ColorFromGray[1.0-intensity]]}; }; NotYetImplemented: PUBLIC SIGNAL = CODE; <> Transform: PUBLIC PROC [sliceD: SliceDescriptor, scene: Scene, transform: Matrix4by4] = { shape: Shape _ NARROW[sliceD.slice.shape]; mo: MasterObject _ shape.mo; mo.class.transform[sliceD, scene, transform]; UpdateBoundBoxes[sliceD.slice]; }; <> IncTransf: PUBLIC PROC [c: Slice, scene: Scene, m: Matrix4by4, d: CoordSystem _ NIL, dFixed: BOOL _ FALSE, cameraList: LIST OF Camera _ NIL] = { <> assemCS: CoordSystem _ c.coordSys; IF d = NIL THEN d _ scene.coordSysRoot; IncTransfCS[assemCS, d, m, dFixed]; UpdateBoundBoxes[c, cameraList]; }; IncTransfMatrix: PUBLIC PROC [c: Slice, dWorld: Matrix4by4, m: Matrix4by4, cameraList: LIST OF Camera _ NIL] = { p: CoordSystem; cWorld, pWorld: Matrix4by4; assemCS: CoordSystem _ c.coordSys; p _ CoordSys.Parent[assemCS]; IF p = NIL THEN ERROR; -- cannot translate WORLD for now cWorld _ CoordSys.WRTWorld[assemCS]; pWorld _ CoordSys.WRTWorld[p]; CoordSys.SetMat[assemCS, SVMatrixOps.IncTransf[cWorld, pWorld, dWorld, m]]; UpdateBoundBoxes[c, cameraList]; }; IncTransfCS: PUBLIC PROC [c: CoordSystem, d: CoordSystem, m: Matrix4by4, dFixed: BOOL _ FALSE] = { <> p: CoordSystem; cWorld, dWorld, pWorld: Matrix4by4; <> p _ CoordSys.Parent[c]; IF p = NIL THEN ERROR; -- cannot translate WORLD for now IF d = NIL THEN ERROR; cWorld _ CoordSys.WRTWorld[c]; pWorld _ CoordSys.WRTWorld[p]; dWorld _ CoordSys.WRTWorld[d]; CoordSys.SetMat[c, SVMatrixOps.IncTransf[cWorld, pWorld, dWorld, m]]; IF dFixed THEN SVTransforms.AbsTransfMatrix[d, Matrix3d.Identity[], dWorld]; }; AbsTransf: PUBLIC PROC [c: Slice, scene: Scene, n: Matrix4by4, d: CoordSystem _ NIL, dFixed: BOOL _ FALSE, cameraList: LIST OF Camera _ NIL] = { <> assemCS: CoordSystem _ c.coordSys; IF d = NIL THEN d _ scene.coordSysRoot; AbsTransfCS[assemCS, d, n, dFixed]; UpdateBoundBoxes[c, cameraList]; }; <<>> AbsTransfCS: PUBLIC PROC [c: CoordSystem, d: CoordSystem, n: Matrix4by4, dFixed: BOOL _ FALSE] = { <> p: CoordSystem; dWorld, pWorld: Matrix4by4; IF Rope.Equal[CoordSys.Name[c], "SCREEN", TRUE] THEN {CoordSys.SetMat[c, n]; RETURN}; p _ CoordSys.Parent[c]; IF p = NIL THEN ERROR; -- cannot transform WORLD. IF d = NIL THEN ERROR; <> <> <> dWorld _ CoordSys.WRTWorld[d]; pWorld _ CoordSys.WRTWorld[p]; CoordSys.SetMat[c, SVMatrixOps.AbsTransf[pWorld, dWorld, n]]; IF dFixed THEN SVTransforms.AbsTransfMatrix[d, Matrix3d.Identity[], dWorld]; }; TugTransf: PUBLIC PROC [c: Slice, scene: Scene, tugBoat: CoordSystem, n: Matrix4by4, d: CoordSystem _ NIL, cameraList: LIST OF Camera _ NIL] = { <> assemCS: CoordSystem _ c.coordSys; IF d = NIL THEN d _ scene.coordSysRoot; TugTransfCS[assemCS, tugBoat, d, n]; UpdateBoundBoxes[c, cameraList]; }; TugTransfCS: PUBLIC PROC [C: CoordSystem, tugBoat: CoordSystem, D: CoordSystem, N: Matrix4by4] = { F: Matrix4by4 _ CoordSys.FindAInTermsOfB[C, tugBoat]; AbsTransfCS[tugBoat, D, N]; AbsTransfCS[C, tugBoat, F]; }; TugTransfLeaveTug: PUBLIC PROC [c: Slice, scene: Scene, tugBoat: CoordSystem, n: Matrix4by4, d: CoordSystem _ NIL, cameraList: LIST OF Camera _ NIL] = { <> assemCS: CoordSystem _ c.coordSys; IF d = NIL THEN d _ scene.coordSysRoot; TugTransfLeaveTugCS[assemCS, tugBoat, d, n]; UpdateBoundBoxes[c, cameraList]; }; TugTransfLeaveTugCS: PUBLIC PROC [C: CoordSystem, tugBoat: CoordSystem, D: CoordSystem, N: Matrix4by4] = { <> F: Matrix4by4; saveTugMat: Matrix4by4 _ CoordSys.GetMat[tugBoat]; F _ CoordSys.FindAInTermsOfB[C, tugBoat]; AbsTransfCS[tugBoat, D, N]; AbsTransfCS[C, tugBoat, F]; CoordSys.SetMat[tugBoat, saveTugMat]; }; ScalePrimitive: PUBLIC PROC [c: Slice, sx, sy, sz: REAL, cameraList: LIST OF Camera _ NIL] = { shape: Shape; scalarCS: CoordSystem; scalars: Vector3d; IF NOT ISTYPE[c.shape, Shape] THEN ERROR; shape _ NARROW[c.shape]; scalarCS _ shape.coordSys; scalars _ CoordSys.GetScalars[scalarCS]; scalars[1] _ scalars[1]*sx; scalars[2] _ scalars[2]*sy; scalars[3] _ scalars[3]*sz; CoordSys.SetScalars[scalarCS, scalars]; UpdateBoundBoxes[c, cameraList]; }; MatrixHasScaling: PRIVATE PROC [mat: Matrix4by4] RETURNS [BOOL] = { sx, sy, sz: REAL; almostZero: REAL _ 1.0e-4; [sx, sy, sz] _ Matrix3d.ScaleFromMatrix[mat]; IF ABS[sx - 1.0] > almostZero OR ABS[sy-1.0] > almostZero OR ABS[sz - 1.0] > almostZero THEN RETURN[TRUE] ELSE RETURN [FALSE]; }; Describe: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [rope: Rope.ROPE] = { shape: Shape _ NARROW[sliceD.slice.shape]; mo: MasterObject _ shape.mo; RETURN[mo.class.describe[sliceD]]; }; DescribeHit: PUBLIC PROC [slice: Slice, hitData: REF ANY] RETURNS [rope: Rope.ROPE] = { shape: Shape _ NARROW[slice.shape]; mo: MasterObject _ shape.mo; RETURN[mo.class.describeHit[mo, hitData]]; }; <<>> <> EmptyParts: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [BOOL] = { shape: Shape _ NARROW[sliceD.slice.shape]; mo: MasterObject _ shape.mo; IF sliceD.parts = NIL THEN RETURN[TRUE]; RETURN[mo.class.emptyParts[sliceD]]; }; NewParts: PUBLIC PROC [slice: Slice, hitData: REF ANY, hitPoint: Point3d, mode: SelectMode] RETURNS [sliceD: SliceDescriptor] = { shape: Shape _ NARROW[slice.shape]; mo: MasterObject _ shape.mo; RETURN[mo.class.newParts[slice, hitData, hitPoint, mode]]; }; DescriptorFromParts: PUBLIC PROC [slice: Slice, parts: SliceParts] RETURNS [sliceD: SliceDescriptor] = { sliceD _ NEW[SliceDescriptorObj _ [slice, parts]]; }; <<>> UnionParts: PUBLIC PROC [partsA: SliceDescriptor, partsB: SliceDescriptor] RETURNS [aPlusB: SliceDescriptor] = { shape: Shape; mo: MasterObject; IF partsA = NIL AND partsB = NIL THEN RETURN[NIL]; IF partsA = NIL THEN shape _ NARROW[partsB.slice.shape] ELSE shape _ NARROW[partsA.slice.shape]; mo _ shape.mo; RETURN[mo.class.unionParts[partsA, partsB]]; }; DifferenceParts: PUBLIC PROC [partsA: SliceDescriptor, partsB: SliceDescriptor] RETURNS [aMinusB: SliceDescriptor] = { shape: Shape; mo: MasterObject; IF partsA = NIL AND partsB = NIL THEN RETURN[NIL]; IF partsA = NIL THEN shape _ NARROW[partsB.slice.shape] ELSE shape _ NARROW[partsA.slice.shape]; mo _ shape.mo; RETURN[mo.class.differenceParts[partsA, partsB]]; }; MovingParts: PUBLIC PROC [slice: Slice, selectedParts: SliceParts] RETURNS [background, overlay, rubber, drag: SliceDescriptor] = { shape: Shape _ NARROW[slice.shape]; mo: MasterObject _ shape.mo; [background, overlay, rubber, drag] _ mo.class.movingParts[slice, selectedParts]; }; AugmentParts: PUBLIC PROC [sliceD: SliceDescriptor, selectClass: SelectionClass] RETURNS [more: SliceDescriptor] = { mo: MasterObject; mo _ NARROW[sliceD.slice.shape, Shape].mo; more _ mo.class.augmentParts[sliceD, selectClass]; }; <> PointsInDescriptor: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [PointGenerator] = { assembly: Slice; mo: MasterObject; shape: Shape; assembly _ sliceD.slice; shape _ NARROW[assembly.shape]; mo _ shape.mo; RETURN[mo.class.pointsInDescriptor[sliceD]]; }; NextPoint: PUBLIC PROC [pointGen: PointGenerator] RETURNS [pointAndDone: PointAndDone] = { assembly: Slice; mo: MasterObject; shape: Shape; ptBlockandDone: PointAndDone; blockWORLD: Matrix4by4; assembly _ pointGen.sliceD.slice; shape _ NARROW[assembly.shape]; mo _ shape.mo; ptBlockandDone _ mo.class.nextPoint[pointGen]; IF ptBlockandDone.done THEN RETURN[[[0,0,0], TRUE]]; blockWORLD _ CoordSys.WRTWorld[shape.coordSys]; pointAndDone.point _ Matrix3d.Update[ptBlockandDone.point, blockWORLD]; pointAndDone.done _ FALSE; }; PointPairsInDescriptor: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [pointPairGen: PointPairGenerator] = { assembly: Slice; mo: MasterObject; shape: Shape; assembly _ sliceD.slice; shape _ NARROW[assembly.shape]; mo _ shape.mo; RETURN[mo.class.pointPairsInDescriptor[sliceD]]; }; NextPointPair: PUBLIC PROC [pointPairGen: PointPairGenerator] RETURNS [pointPairAndDone: PointPairAndDone] = { assembly: Slice; mo: MasterObject; shape: Shape; pointPairShapeandDone: PointPairAndDone; shapeWorld: Matrix4by4; assembly _ pointPairGen.sliceD.slice; shape _ NARROW[assembly.shape]; mo _ shape.mo; pointPairShapeandDone _ mo.class.nextPointPair[pointPairGen]; IF pointPairShapeandDone.done THEN RETURN[[[0,0,0], [0,0,0], TRUE]]; shapeWorld _ CoordSys.WRTWorld[shape.coordSys]; pointPairAndDone.lo _ Matrix3d.Update[pointPairShapeandDone.lo, shapeWorld]; pointPairAndDone.hi _ Matrix3d.Update[pointPairShapeandDone.hi, shapeWorld]; pointPairAndDone.done _ FALSE; }; <> ClosestPointToPoint: PUBLIC PROC [sliceD: SliceDescriptor, testPoint: Point3d, t: REAL] RETURNS [bestDist: REAL, pointWorld: Point3d, normalWorld: Vector3d, hitData: REF ANY, success: BOOL] = { mo: MasterObject; mo _ NARROW[sliceD.slice.shape, Shape].mo; [bestDist, pointWorld, normalWorld, hitData, success] _ mo.class.closestPointToPoint[sliceD, testPoint, t]; }; ClosestPointToLine: PUBLIC PROC [sliceD: SliceDescriptor, cameraPoint: Point2d, line3d: Line3d, t: REAL, camera: Camera] RETURNS [bestDist: REAL, pointWorld: Point3d, normalWorld: Vector3d, hitData: REF ANY, success: BOOL] = { mo: MasterObject; mo _ NARROW[sliceD.slice.shape, Shape].mo; [bestDist, pointWorld, normalWorld, hitData, success] _ mo.class.closestPointToLine[sliceD, cameraPoint, line3d, t, camera]; }; ClosestSegmentToLine: PUBLIC PROC [sliceD: SliceDescriptor, cameraPoint: Point2d, line3d: Line3d, t: REAL, camera: Camera] RETURNS [bestDist: REAL, pointWorld: Point3d, normalWorld: Vector3d, hitData: REF ANY, success: BOOL] = { mo: MasterObject; mo _ NARROW[sliceD.slice.shape, Shape].mo; [bestDist, pointWorld, normalWorld, hitData, success] _ mo.class.closestSegmentToLine[sliceD, cameraPoint, line3d, t, camera]; }; ClosestJointToHitData: PUBLIC PROC [sliceD: SliceDescriptor, worldPt: Point3d, normal: Vector3d, hitData: REF ANY] RETURNS [jointD: SliceDescriptor, jointPos: Point3d, jointNormal: Vector3d] = { <> newHitData: REF ANY; success: BOOL; dist: REAL; jointD _ sliceD; [dist, jointPos, jointNormal, newHitData, success] _ ClosestPointToPoint[sliceD, worldPt, Real.LargestNumber]; IF NOT success THEN ERROR; <> }; END.