<> <> <> DIRECTORY SV2d, SV3d, SVBoundBox, SVFaces, SVLines2d, SVModelTypes, SVVector2d, SVVector3d; SVFacesImpl: CEDAR PROGRAM IMPORTS SVBoundBox, SVLines2d, SVVector2d, SVVector3d EXPORTS SVFaces = BEGIN TrigLineSeg: TYPE = SV2d.TrigLineSeg; Vector3d: TYPE = SV3d.Vector3d; Vector2d: TYPE = SV2d.Vector2d; <> Cone: TYPE = REF ConeObj; ConeObj: TYPE = SVFaces.ConeObj; <= 0 AND rOut > rIn, and may have an upward or downward pointing normal.>> DiskRing: TYPE = REF DiskRingObj; DiskRingObj: TYPE = SVFaces.DiskRingObj; < yLow and may have an arbitrary radius r.>> Cylinder: TYPE = REF CylinderObj; CylinderObj: TYPE = SVFaces.CylinderObj; <> EdgeOnRect: TYPE = REF EdgeOnRectObj; EdgeOnRectObj: TYPE = SVFaces.EdgeOnRectObj; Abs: PROC [r: REAL] RETURNS [REAL] = { RETURN[IF r >= 0 THEN r ELSE -r]; }; -- end of Abs ConeFromTrigLineSeg: PUBLIC PROC [seg: TrigLineSeg] RETURNS [cone: Cone] = { isParallel: BOOL; x, y: REAL; signHi, signLo: PosNeg; cone _ NEW[ConeObj]; [cone.h, isParallel] _ SVLines2d.TrigLineMeetsYAxis[seg.line]; IF isParallel THEN ERROR AttemptToCreateDegenerateCone; <> IF seg.pLo[2] = seg.pHi[2] THEN ERROR AttemptToCreateDegenerateCone; <> <> <> <> <> x _ IF Abs[seg.pLo[1]] > Abs[seg.pHi[1]] THEN Abs[seg.pLo[1]] ELSE Abs[seg.pHi[1]]; y _ (x*seg.line.s + seg.line.d)/seg.line.c; cone.M _ x/Abs[y - cone.h]; <> <> <> <> <> <> <> <> cone.yHi _ seg.pHi[2]; cone.yLo _ seg.pLo[2]; signHi _ Sign[cone.yHi - cone.h]; signLo _ Sign[cone.yLo - cone.h]; IF signHi # signLo AND signHi # zero AND signLo # zero THEN ERROR AttemptToCreateDegenerateCone; IF cone.yHi > cone.h THEN cone.noseIsUp _ FALSE ELSE cone.noseIsUp _ TRUE; <> <> <> <> IF seg.line.theta < 0 THEN cone.normalPointsOut _ TRUE ELSE cone.normalPointsOut _ FALSE; <> cone.boundHedron _ SVBoundBox.GeneralConeBoundHedron[seg.pHi[1], seg.pHi[2], seg.pLo[1], seg.pLo[2]]; }; -- end of ConeFromTrigLineSeg AttemptToCreateDegenerateCone: PUBLIC ERROR = CODE; PosNeg: TYPE = {pos, neg, zero}; Sign: PROC [r: REAL] RETURNS [sign: PosNeg] = { RETURN[IF r > 0 THEN pos ELSE IF r < 0 THEN neg ELSE zero]; }; DiskRingFromTrigLineSeg: PUBLIC PROC [seg: TrigLineSeg] RETURNS [diskRing: DiskRing] = { <> x1, x2: REAL; diskRing _ NEW[DiskRingObj]; <> IF seg.pLo[2] # seg.pHi[2] THEN ERROR AttemptToCreateDegenerateDiskRing; diskRing.yPlane _ seg.pLo[2]; IF seg.pLoIsFirst THEN { x1 _ seg.pLo[1]; x2 _ seg.pHi[1]} ELSE {x1 _ seg.pHi[1]; x2 _ seg.pLo[1]}; < x1;>> IF Sign[x1] # Sign[x2] AND Sign[x1] # zero AND Sign[x2] # zero THEN ERROR AttemptToCreateDegenerateDiskRing; x1 _ Abs[x1]; x2 _ Abs[x2]; <> IF x2 > x1 THEN { diskRing.normal _ [0,1,0]; diskRing.rInSquared _ x1*x1; diskRing.rOutSquared _ x2*x2; diskRing.boundHedron _ SVBoundBox.DiskBoundHedron[r: x2, h: seg.pLo[2]]} ELSE { diskRing.normal _ [0,-1,0]; diskRing.rInSquared _ x2*x2; diskRing.rOutSquared _ x1*x1; diskRing.boundHedron _ SVBoundBox.DiskBoundHedron[r: x1, h: seg.pLo[2]]}; }; -- end of DiskRingFromTrigLineSeg AttemptToCreateDegenerateDiskRing: PUBLIC ERROR = CODE; CylinderFromTrigLineSeg: PUBLIC PROC [seg: TrigLineSeg] RETURNS [cylinder: Cylinder] = { cylinder _ NEW[CylinderObj]; <> IF seg.pLo[1] # seg.pHi[1] THEN ERROR AttemptToCreateDegenerateCylinder; <> IF seg.line.theta < 0 THEN cylinder.normalPointsOut _ TRUE ELSE cylinder.normalPointsOut _ FALSE; cylinder.yHi _ seg.pHi[2]; cylinder.yLo _ seg.pLo[2]; cylinder.r _ seg.pLo[1]; cylinder.rSquared _ cylinder.r*cylinder.r; cylinder.boundHedron _ SVBoundBox.GeneralConeBoundHedron[seg.pLo[1], seg.pHi[2], seg.pLo[1], seg.pLo[2]]; }; AttemptToCreateDegenerateCylinder: PUBLIC ERROR = CODE; EdgeOnRectFromTrigLineSeg: PUBLIC PROC [seg: TrigLineSeg, frontZ, backZ: REAL] RETURNS [edgeOnRect: EdgeOnRect] = { <> <> <> <> normal2d: Vector2d; edgeOnRect _ NEW[EdgeOnRectObj]; edgeOnRect.frontZ _ frontZ; edgeOnRect.backZ _ backZ; edgeOnRect.A _ -seg.line.s; edgeOnRect.B _ seg.line.c; edgeOnRect.D _ -seg.line.d; <> normal2d _ SVVector2d.LeftNormalOfTrigLineSeg[seg]; edgeOnRect.normal _ SVVector3d.Vector2DAsXYVector[vXY: normal2d]; IF (45 <= seg.line.theta AND seg.line.theta <= 135) OR (-135 <= seg.line.theta AND seg.line.theta <= -45) THEN { edgeOnRect.valIsY _ TRUE; edgeOnRect.valLo _ seg.pLo[2]; edgeOnRect.valHi _ seg.pHi[2]; } ELSE { edgeOnRect.valIsY _ FALSE; edgeOnRect.valLo _ Min[seg.pLo[1], seg.pHi[1]]; edgeOnRect.valHi _ Max[seg.pLo[1], seg.pHi[1]]; }; }; -- end of EdgeOnRectFromTrigLineSeg AttemptToCreateDegenerateEdgeOnRect: PUBLIC ERROR = CODE; Max: PRIVATE PROC [a, b: REAL] RETURNS [REAL] = { RETURN [IF a>b THEN a ELSE b]; }; Min: PRIVATE PROC [a, b: REAL] RETURNS [REAL] = { RETURN [IF a