DIRECTORY CADIO, CADTypes USING [CellRec, CellSequence, CompoundOperator, QuantifierFreeFormula, QuantifierFreeFormulaSequence, Scad, SimpleOperator, TriangleSequence, VariableRec, VertexSequence, VisibleMask], Convert, FormulaOperators, Formulas, FS USING [StreamOpen], Interminal USING [MousePosition], IO USING [BreakProc, Close, CR, GetTokenRope, IDProc, int, NUL, PutF, PutFR, real, rope, SP, STREAM], MultiPolynomial USING [EvaluationBindings, RefFromRope, RopeFromRef, TotallyEvaluate], AlgebraClasses, Ints, Polynomials, PopUpMenu USING [RequestSelection], Points, Sequences, CoveringSets, Triangles, Cells, Cads, Reals, Rope USING [Compare, Concat, ROPE], Vector3d USING [Triple]; CADIOImpl: CEDAR PROGRAM IMPORTS Convert, FS, IO, MultiPolynomial, Polynomials, PopUpMenu, Triangles, Cads, Rope EXPORTS CADIO ~ BEGIN Error: PUBLIC ERROR[why: ATOM] = CODE; ReadVAXCadFiles: PUBLIC PROC [cadFile, csFile: Rope.ROPE] RETURNS [info: CADTypes.Scad] ~ BEGIN cadStream, csStream: IO.STREAM; qeCad: Cads.Cad; qeCadData: Cads.CadData; oldCellsData: Sequences.SequenceData; polySeqData: Sequences.SequenceData; cellData: Cells.CellData; pointData: Points.PointData; inputPoly: Polynomials.Polynomial; cadStructure: AlgebraClasses.Structure _ Cads. MakeCadStructure[]; surfaceRope: Rope.ROPE; oldCells: Sequences.Sequence; numberOfOldCells: NAT; newCells: REF CADTypes.CellSequence; newCellIndex: NAT; compressedNewCells: REF CADTypes.CellSequence; TranslateQFF: PROC [old: Formulas.Formula] RETURNS [new: CADTypes.QuantifierFreeFormula] ~ BEGIN oldData: Formulas.FormulaData _ NARROW[old.data]; mainOp: FormulaOperators.Op _ NARROW[oldData.mainOperator.data, FormulaOperators.OperatorData]^; IF oldData.atomicMatrix THEN BEGIN newOperator: CADTypes.SimpleOperator; SELECT mainOp FROM lt => newOperator _ isNegative; gt => newOperator _ isPositive; eq => newOperator _ isZero; le, ge, ne => ERROR Error[$UnimplementedOperator]; ENDCASE => ERROR Error[$BadOperator]; RETURN [[ isCompound: FALSE, compoundOperator: none, compoundArguments: NIL, simpleOperator: newOperator, simpleArgument: MultiPolynomial.RefFromRope[Polynomials.ToRope[oldData.polynomial]] ]]; END ELSE BEGIN newOperator: CADTypes.CompoundOperator; newOperands: REF CADTypes.QuantifierFreeFormulaSequence; oldOperands: LIST OF Formulas.Formula; nOperands: NAT; SELECT mainOp FROM and => newOperator _ and; or => newOperator _ or; not => ERROR Error[$UnimplementedOperator]; ENDCASE => ERROR Error[$BadOperator]; nOperands _ 0; oldOperands _ oldData.operands; UNTIL oldOperands = NIL DO nOperands _ nOperands + 1; oldOperands _ oldOperands.rest; ENDLOOP; newOperands _ NEW[CADTypes.QuantifierFreeFormulaSequence[nOperands]]; oldOperands _ oldData.operands; FOR i: NAT IN [0..nOperands) DO newOperands[i] _ TranslateQFF[oldOperands.first]; oldOperands _ oldOperands.rest; ENDLOOP; RETURN [[ isCompound: TRUE, compoundOperator: newOperator, compoundArguments: newOperands, simpleOperator: none, simpleArgument: NIL ]]; END; END; cadStream _ FS.StreamOpen[cadFile]; qeCad _ cadStructure.class.read[cadStream, cadStructure]; csStream _ FS.StreamOpen[csFile]; qeCad _ Cads.ReadCSets[csStream, qeCad]; qeCadData _ NARROW[qeCad.data]; polySeqData _ NARROW[qeCadData.inputPolynomials.data]; inputPoly _ polySeqData[1]; surfaceRope _ inputPoly.structure.class.toRope[inputPoly]; oldCells _ qeCadData.cells; oldCellsData _ NARROW[oldCells.data]; numberOfOldCells _ oldCellsData.lengthPlus1 - 1; newCells _ NEW[CADTypes.CellSequence[numberOfOldCells]]; newCellIndex _ 0; FOR oldCellIndex: NAT IN [1..numberOfOldCells] DO cellData _ NARROW[oldCellsData[oldCellIndex].data]; pointData _ NARROW[cellData.index.data]; IF NARROW[pointData[3].data, Ints.IntData]^ MOD 2 = 0 THEN BEGIN newCells[newCellIndex].indexX _ NARROW[pointData[1].data, Ints.IntData]^; newCells[newCellIndex].indexY _ NARROW[pointData[2].data, Ints.IntData]^; newCells[newCellIndex].indexZ _ NARROW[pointData[3].data, Ints.IntData]^; newCells[newCellIndex].dimension _ cellData.dimension; newCells[newCellIndex].definingFormula _ TranslateQFF[cellData.definingFormula]; SELECT newCells[newCellIndex].dimension FROM 0 => BEGIN xReal, yReal, zReal: REAL; coveringSetData: CoveringSets.CoveringSetData _ NARROW[cellData.coveringSet.data]; setData: Sequences.SequenceData _ NARROW[coveringSetData.dataPoints.data]; columnData: Sequences.SequenceData _ NARROW[setData[1].data]; pointData: Points.PointData _ NARROW[columnData[1].data ]; newCells[newCellIndex].vertices _ NEW[CADTypes.VertexSequence[1]]; xReal _ NARROW[pointData[1].data, Reals.RealData]^; yReal _ NARROW[pointData[2].data, Reals.RealData]^; zReal _ NARROW[pointData[3].data, Reals.RealData]^; newCells[newCellIndex].vertices[0] _ [ x: xReal, y: yReal, z: zReal ]; newCells[newCellIndex].polygons _ NEW[CADTypes.TriangleSequence[0]]; END; 1 => BEGIN coveringSetData: CoveringSets.CoveringSetData _ NARROW[cellData.coveringSet.data]; setData: Sequences.SequenceData _ NARROW[coveringSetData.dataPoints.data]; columnData: Sequences.SequenceData _ NARROW[setData[1].data]; numberOfPoints: NAT _ columnData.lengthPlus1 - 1; newCells[newCellIndex].vertices _ NEW[CADTypes.VertexSequence[numberOfPoints]]; FOR j: NAT IN [0..numberOfPoints) DO xReal, yReal, zReal: REAL; pointData: Points.PointData _ NARROW[columnData[j + 1].data ]; xReal _ NARROW[pointData[1].data, Reals.RealData]^; yReal _ NARROW[pointData[2].data, Reals.RealData]^; zReal _ NARROW[pointData[3].data, Reals.RealData]^; newCells[newCellIndex].vertices[j] _ [ x: xReal, y: yReal, z: zReal ]; ENDLOOP; newCells[newCellIndex].polygons _ NEW[CADTypes.TriangleSequence[0]]; END; 2 => BEGIN numberOfPoints, pointIndex: NAT; triangulation: Triangles.TriangleSeq; coveringSetData: CoveringSets.CoveringSetData _ NARROW[cellData.coveringSet.data]; setData: Sequences.SequenceData _ NARROW[coveringSetData.dataPoints.data]; numberOfPoints _ 0; FOR i: NAT IN [1..setData.lengthPlus1) DO columnData: Sequences.SequenceData _ NARROW[setData[i].data]; numberOfPoints _ numberOfPoints + columnData.lengthPlus1 - 1; ENDLOOP; newCells[newCellIndex].vertices _ NEW[CADTypes.VertexSequence[numberOfPoints]]; pointIndex _ 0; FOR i: NAT IN [1..setData.lengthPlus1) DO columnData: Sequences.SequenceData _ NARROW[setData[i].data]; FOR j: NAT IN [1..columnData.lengthPlus1) DO xReal, yReal, zReal: REAL; pointData: Points.PointData _ NARROW[columnData[j].data ]; xReal _ NARROW[pointData[1].data, Reals.RealData]^; yReal _ NARROW[pointData[2].data, Reals.RealData]^; zReal _ NARROW[pointData[3].data, Reals.RealData]^; newCells[newCellIndex].vertices[pointIndex] _ [ x: xReal, y: yReal, z: zReal ]; pointIndex _ pointIndex + 1; ENDLOOP; ENDLOOP; triangulation _ Triangles.GenerateTriangles[cellData.coveringSet]; IF triangulation = NIL THEN newCells[newCellIndex].polygons _ NEW[CADTypes.TriangleSequence[0]] ELSE { newCells[newCellIndex].polygons _ NEW[CADTypes.TriangleSequence [triangulation.trianglesPlusOne - 1]]; FOR i: NAT IN [1..triangulation.trianglesPlusOne) DO newCells[newCellIndex].polygons[i - 1] _ [ firstVertex: triangulation[i].firstVertex, secondVertex: triangulation[i].secondVertex, thirdVertex: triangulation[i].thirdVertex ]; ENDLOOP; }; END; ENDCASE => BEGIN ERROR Error[$DegreeOutOfRange]; END; newCellIndex _ newCellIndex + 1; END; ENDLOOP; compressedNewCells _ NEW[CADTypes.CellSequence[newCellIndex]]; FOR i: NAT IN [0..newCellIndex) DO compressedNewCells[i] _ newCells[i]; ENDLOOP; info _ [ surface: MultiPolynomial.RefFromRope[surfaceRope], named: FALSE, name: "(none)", color: [1, 1, 1], cells: compressedNewCells]; END; ReadInfoFile: PUBLIC PROC [filename: Rope.ROPE] RETURNS [info: CADTypes.Scad] ~ BEGIN infoStream: IO.STREAM _ FS.StreamOpen[filename]; token: Rope.ROPE _ ""; InfoFileError: ERROR = CODE; TestError: ERROR = CODE; Break: SIGNAL = CODE; BreakProc: IO.BreakProc ~ IO.IDProc; numberOfCells: NAT; TokenBreakProc: IO.BreakProc ~ BEGIN RETURN [SELECT char FROM IN [IO.NUL .. IO.SP], '$ => sepr, ENDCASE => other ]; END; PolynomialBreakProc: IO.BreakProc ~ BEGIN RETURN [SELECT char FROM '$, IO.CR => break, ENDCASE => other ]; END; NextToken: PROC [proc: IO.BreakProc _ TokenBreakProc] RETURNS [Rope.ROPE] ~ BEGIN token: Rope.ROPE; [token: token] _ IO.GetTokenRope[infoStream, proc]; RETURN [token]; END; GetDefiningFormula: PROC RETURNS [CADTypes.QuantifierFreeFormula] ~ BEGIN operatorRope: Rope.ROPE; simpleOperator: CADTypes.SimpleOperator; compoundOperator: CADTypes.CompoundOperator; isCompound: BOOLEAN; operatorRope _ NextToken[]; IF Rope.Compare[operatorRope, "IsPositive"] = equal THEN {simpleOperator _ isPositive; isCompound _ FALSE} ELSE IF Rope.Compare[operatorRope, "IsZero"] = equal THEN {simpleOperator _ isZero; isCompound _ FALSE} ELSE IF Rope.Compare[operatorRope, "IsNegative"] = equal THEN {simpleOperator _ isNegative; isCompound _ FALSE} ELSE IF Rope.Compare[operatorRope, "And"] = equal THEN {compoundOperator _ and; isCompound _ TRUE} ELSE IF Rope.Compare[operatorRope, "Or"] = equal THEN {compoundOperator _ or; isCompound _ TRUE} ELSE ERROR InfoFileError; IF ~isCompound THEN BEGIN polyRope: Rope.ROPE _ NextToken[PolynomialBreakProc]; RETURN [[ isCompound: FALSE, compoundOperator: none, compoundArguments: NIL, simpleOperator: simpleOperator, simpleArgument: MultiPolynomial.RefFromRope[polyRope] ]]; END ELSE BEGIN numberOfArguments: NAT _ Convert.IntFromRope[NextToken[]]; qff: CADTypes.QuantifierFreeFormula _ [ isCompound: TRUE, compoundOperator: compoundOperator, compoundArguments: NEW[CADTypes.QuantifierFreeFormulaSequence[numberOfArguments]], simpleOperator: none, simpleArgument: NIL]; FOR argument: NAT IN [0..numberOfArguments) DO qff.compoundArguments[argument] _ GetDefiningFormula[]; ENDLOOP; RETURN [qff]; END; END; UNTIL Rope.Compare[token, "BEGIN"] = equal DO token _ NextToken[]; ENDLOOP; IF Rope.Compare[NextToken[], "CAD"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "DESCRIPTION"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "Surface"] # equal THEN ERROR InfoFileError; token _ NextToken[PolynomialBreakProc]; info.surface _ MultiPolynomial.RefFromRope[token]; IF Rope.Compare[NextToken[], "Name"] # equal THEN ERROR InfoFileError; token _ NextToken[]; IF Rope.Compare[token, "UNNAMED"] = equal THEN BEGIN info.named _ FALSE; info.name _ "(unnamed)"; END ELSE BEGIN info.named _ TRUE; info.name _ token; END; IF Rope.Compare[NextToken[], "Color"] # equal THEN ERROR InfoFileError; info.color.R _ Convert.RealFromRope[NextToken[]]; info.color.G _ Convert.RealFromRope[NextToken[]]; info.color.B _ Convert.RealFromRope[NextToken[]]; IF Rope.Compare[NextToken[], "Cells"] # equal THEN ERROR InfoFileError; numberOfCells _ Convert.IntFromRope[NextToken[]]; info.cells _ NEW[CADTypes.CellSequence[numberOfCells]]; IF Rope.Compare[NextToken[], "BEGIN"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "CELL"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "DEFINITIONS"] # equal THEN ERROR InfoFileError; FOR cell: NAT IN [0..numberOfCells) DO dimension: CARDINAL; IF Rope.Compare[NextToken[], "CellIndices"] # equal THEN ERROR InfoFileError; info.cells[cell].indexX _ Convert.IntFromRope[NextToken[]]; info.cells[cell].indexY _ Convert.IntFromRope[NextToken[]]; info.cells[cell].indexZ _ Convert.IntFromRope[NextToken[]]; IF Rope.Compare[NextToken[], "CellDegree"] # equal THEN ERROR InfoFileError; dimension _ Convert.CardFromRope[NextToken[]]; IF dimension > 2 THEN ERROR InfoFileError; info.cells[cell].dimension _ dimension; IF Rope.Compare[NextToken[], "DefiningFormula"] # equal THEN ERROR InfoFileError; info.cells[cell].definingFormula _ GetDefiningFormula[]; ENDLOOP; IF Rope.Compare[NextToken[], "END"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "CELL"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "DEFINITIONS"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "BEGIN"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "CELL"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "DISPLAY"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "INFORMATION"] # equal THEN ERROR InfoFileError; FOR cell: NAT IN [0..numberOfCells) DO dimension: CARDINAL; nVertices, nTriangles: NAT; IF Rope.Compare[NextToken[], "Indices"] # equal THEN ERROR InfoFileError; IF Convert.IntFromRope[NextToken[]] # info.cells[cell].indexX THEN ERROR InfoFileError; IF Convert.IntFromRope[NextToken[]] # info.cells[cell].indexY THEN ERROR InfoFileError; IF Convert.IntFromRope[NextToken[]] # info.cells[cell].indexZ THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "Degree"] # equal THEN ERROR InfoFileError; dimension _ Convert.CardFromRope[NextToken[]]; IF dimension # info.cells[cell].dimension THEN ERROR InfoFileError; IF dimension = 0 THEN BEGIN IF Rope.Compare[NextToken[], "Position"] # equal THEN ERROR InfoFileError; info.cells[cell].vertices _ NEW[CADTypes.VertexSequence[1]]; info.cells[cell].vertices[0].x _ Convert.RealFromRope[NextToken[]]; info.cells[cell].vertices[0].y _ Convert.RealFromRope[NextToken[]]; info.cells[cell].vertices[0].z _ Convert.RealFromRope[NextToken[]]; END ELSE IF dimension = 1 OR dimension = 2 THEN BEGIN IF Rope.Compare[NextToken[], "Vertices"] # equal THEN ERROR InfoFileError; nVertices _ Convert.IntFromRope[NextToken[]]; info.cells[cell].vertices _ NEW[CADTypes.VertexSequence[nVertices]]; FOR i: NAT IN [0..nVertices) DO info.cells[cell].vertices[i].x _ Convert.RealFromRope[NextToken[]]; info.cells[cell].vertices[i].y _ Convert.RealFromRope[NextToken[]]; info.cells[cell].vertices[i].z _ Convert.RealFromRope[NextToken[]]; ENDLOOP; END ELSE ERROR InfoFileError; IF dimension = 2 THEN BEGIN IF Rope.Compare[NextToken[], "Triangles"] # equal THEN ERROR InfoFileError; nTriangles _ Convert.IntFromRope[NextToken[]]; info.cells[cell].polygons _ NEW[CADTypes.TriangleSequence[nTriangles]]; FOR i: NAT IN [0..nTriangles) DO info.cells[cell].polygons[i].firstVertex _ Convert.IntFromRope[NextToken[]]; info.cells[cell].polygons[i].secondVertex _ Convert.IntFromRope[NextToken[]]; info.cells[cell].polygons[i].thirdVertex _ Convert.IntFromRope[NextToken[]]; ENDLOOP; END ELSE BEGIN info.cells[cell].polygons _ NEW[CADTypes.TriangleSequence[0]]; END; ENDLOOP; IF Rope.Compare[NextToken[], "END"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "CELL"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "DISPLAY"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "INFORMATION"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "END"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "CAD"] # equal THEN ERROR InfoFileError; IF Rope.Compare[NextToken[], "DESCRIPTION"] # equal THEN ERROR InfoFileError; END; WriteInfoFile: PUBLIC PROC [filename: Rope.ROPE, info: CADTypes.Scad] ~ BEGIN infoStream: IO.STREAM _ FS.StreamOpen[filename, $create]; InternalError: ERROR = CODE; WriteDefiningFormula: PROC[df: CADTypes.QuantifierFreeFormula, nesting: NAT _ 2] ~ BEGIN operatorRope: Rope.ROPE _ IF df.isCompound THEN SELECT df.compoundOperator FROM and => "And", or => "Or", ENDCASE => ERROR InternalError ELSE SELECT df.simpleOperator FROM isPositive => "IsPositive", isZero => "IsZero", isNegative => "IsNegative" ENDCASE => ERROR InternalError; IF nesting # 2 THEN FOR i: NAT IN [1..nesting] DO IO.PutF[infoStream, "\t"]; ENDLOOP; IF df.isCompound THEN BEGIN IO.PutF[ infoStream, "%g %g\n", IO.rope[operatorRope], IO.int[df.compoundArguments.length]]; FOR formula: NAT IN [0..df.compoundArguments.length) DO WriteDefiningFormula[df.compoundArguments[formula], nesting + 1]; ENDLOOP; END ELSE BEGIN IO.PutF[ infoStream, "%g %g\n", IO.rope[operatorRope], IO.rope[MultiPolynomial.RopeFromRef[df.simpleArgument]]]; END; END; IO.PutF[infoStream, "BEGIN CAD DESCRIPTION\n\n"]; IO.PutF[ infoStream, "\tSurface %g\n", IO.rope[MultiPolynomial.RopeFromRef[info.surface]]]; IF info.named THEN IO.PutF[infoStream, "\tName %g\n", IO.rope[info.name]] ELSE IO.PutF[infoStream, "\tName UNNAMED\n"]; IO.PutF[ infoStream, "\tColor %g %g %g\n", IO.real[info.color.R], IO.real[info.color.G], IO.real[info.color.B]]; IO.PutF[infoStream, "\tCells %g\n", IO.int[info.cells.nCells]]; IO.PutF[infoStream, "\n\tBEGIN CELL DEFINITIONS\n"]; FOR cell: NAT IN [0..info.cells.nCells) DO IO.PutF[ infoStream, "\n\t\tCellIndices %g %g %g\n", IO.int[info.cells[cell].indexX], IO.int[info.cells[cell].indexY], IO.int[info.cells[cell].indexZ]]; IO.PutF[infoStream, "\t\tCellDegree %g\n", IO.int[info.cells[cell].dimension]]; IO.PutF[infoStream, "\t\tDefiningFormula "]; WriteDefiningFormula[info.cells[cell].definingFormula, 2]; ENDLOOP; IO.PutF[infoStream, "\n\tEND CELL DEFINITIONS\n"]; IO.PutF[infoStream, "\n\tBEGIN CELL DISPLAY INFORMATION\n"]; FOR cell: NAT IN [0..info.cells.nCells) DO dimension: CARDINAL _ info.cells[cell].dimension; nVertices: NAT _ info.cells[cell].vertices.nVertices; nTriangles: NAT _ info.cells[cell].polygons.nTriangles; IO.PutF[ infoStream, "\n\t\tIndices %g %g %g\n", IO.int[info.cells[cell].indexX], IO.int[info.cells[cell].indexY], IO.int[info.cells[cell].indexZ]]; IO.PutF[infoStream, "\t\tDegree %g\n", IO.int[dimension]]; IF dimension = 0 THEN IO.PutF[ infoStream, "\t\tPosition %g %g %g\n", IO.real[info.cells[cell].vertices[0].x], IO.real[info.cells[cell].vertices[0].y], IO.real[info.cells[cell].vertices[0].z]] ELSE BEGIN IO.PutF[infoStream, "\t\tVertices %g\n", IO.int[nVertices]]; FOR i: NAT IN [0..nVertices) DO IO.PutF[ infoStream, "\t\t\t%g %g %g\n", IO.real[info.cells[cell].vertices[i].x], IO.real[info.cells[cell].vertices[i].y], IO.real[info.cells[cell].vertices[i].z]]; ENDLOOP; END; IF dimension = 2 THEN BEGIN IO.PutF[infoStream, "\t\tTriangles %g\n", IO.int[nTriangles]]; FOR i: NAT IN [0..nTriangles) DO IO.PutF[ infoStream, "\t\t\t%g %g %g\n", IO.int[info.cells[cell].polygons[i].firstVertex], IO.int[info.cells[cell].polygons[i].secondVertex], IO.int[info.cells[cell].polygons[i].thirdVertex]]; ENDLOOP; END; ENDLOOP; IO.PutF[infoStream, "\n\tEND CELL DISPLAY INFORMATION\n"]; IO.PutF[infoStream, "\nEND CAD DESCRIPTION\n"]; IO.Close[infoStream]; END; SelectCell: PUBLIC PROC [scad: CADTypes.Scad, mask: REF CADTypes.VisibleMask, title: Rope.ROPE] RETURNS [index: INT] ~ BEGIN menuRopes: LIST OF Rope.ROPE _ NIL; mousePosition: REF Interminal.MousePosition; selection: INT; IF scad.cells.nCells # mask.length THEN ERROR Error[$WrongNumberOfCells]; FOR i: INT IN [0..scad.cells.nCells) DO j: NAT _ scad.cells.nCells - i - 1; cell: CADTypes.CellRec _ scad.cells[j]; cellRope: Rope.ROPE _ IO.PutFR["(%g, %g, %g)", IO.int[cell.indexX], IO.int[cell.indexY], IO.int[cell.indexZ]]; IF mask[j] THEN cellRope _ Rope.Concat[cellRope, " V"]; menuRopes _ CONS[cellRope, menuRopes]; ENDLOOP; mousePosition _ NEW[Interminal.MousePosition _ [mouseX: 0, color: FALSE, mouseY: 0]]; selection _ PopUpMenu.RequestSelection[ label: title, choice: menuRopes, timeOut: 0, mouse: mousePosition]; IF (selection = 0) OR (selection = -1) THEN RETURN[-1] ELSE RETURN[selection - 1]; END; WhatCellIsItOn: PUBLIC PROC[point: Vector3d.Triple, variables: CADTypes.VariableRec, scad: CADTypes.Scad] RETURNS [cell: NAT] ~ BEGIN FOR i: NAT IN [0..scad.cells.nCells) DO IF SatisfiesQFF[point, variables, scad.cells[i].definingFormula] THEN RETURN[i]; ENDLOOP; ERROR Error[$NotOnAnyCell]; END; SatisfiesQFF: PROC[point: Vector3d.Triple, variables: CADTypes.VariableRec, qff: CADTypes.QuantifierFreeFormula] RETURNS [satisfiesQFF: BOOLEAN] ~ BEGIN whoops: ERROR = CODE; epsilon: REAL ~ 0.0001; IF qff.isCompound THEN SELECT qff.compoundOperator FROM and => BEGIN FOR i: NAT IN [0..qff.compoundArguments.length) DO IF ~SatisfiesQFF[point, variables, qff.compoundArguments[i]] THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; END; or => BEGIN FOR i: NAT IN [0..qff.compoundArguments.length) DO IF SatisfiesQFF[point, variables, qff.compoundArguments[i]] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; END; ENDCASE => ERROR whoops ELSE BEGIN bindings: MultiPolynomial.EvaluationBindings _ LIST [ [variable: variables.x, value: point.x], [variable: variables.y, value: point.y], [variable: variables.z, value: point.z] ]; evaluatedPol: REAL _ MultiPolynomial.TotallyEvaluate[qff.simpleArgument, bindings]; SELECT qff.simpleOperator FROM isPositive => RETURN[evaluatedPol > 0]; isZero => RETURN[ABS[evaluatedPol] < epsilon]; isNegative => RETURN[evaluatedPol < 0]; ENDCASE => ERROR whoops; END; END; END. šCADIOImpl.mesa James Rauen, August 21, 1986 6:18:48 pm PDT Declarations Here is a procedure that translates quantifier-free-formulas between representations. Translate an atomic formula. Or translate a compound formula. Read the CAD and covering set files. Get the surface equation. Get the old cells and instantiate the new ones. Iterate over the old cells. Only do the cell if it is part of the surface. IF QEIO.CellDimension[oldCells[oldCellIndex].index ] < 3 THEN BEGIN 9/11/86 Do the cell if it has dimension less than 3; clearly wrong; the intent here was just to pick up nasty vertical lines. Translate its indices and dimension. pointData: Points.PointData _ NARROW[oldCells[oldCellIndex].index.data]; Interim calculation of dimension; replace when ReadCad computes it. newCells[newCellIndex].dimension _ (NARROW[oldCells[oldCellIndex].index.data, Points.PointData][1] MOD 2) + (NARROW[oldCells[oldCellIndex].index.data, Points.PointData][2] MOD 2) + (NARROW[oldCells[oldCellIndex].index.data, Points.PointData][3] MOD 2); Translate its defining formula. Translate the vertex and polygon sequences. Count the number of points. numberOfPoints _ 1; newCells[newCellIndex].vertices[0] _ [6, 1, 70]; Translate the points. Generate a triangulation of the points. Translate the triangles. Note! These "triangulations" number the vertices from 1, 2, ..., while the vertices are indexed from 0, 1, .... For example, triangle [firstVertex: 2, secondVertex: 3, thirdVertex: 4] refers to vertices[1], vertices[2], and vertices[3]. The discrepancy is remedied when the 2-cells are written to a temporary file by ThreeDHacks. Increment the index into the new cells. Do the next cell. Compress the new cells. Construct and return the Scad. No guarantees for incorrectly formatted files. Will raise syntax errors. It won't make some checks, such as if vertices listed in the Triangles section actually exist. Declarations Define a break procedure that gets a token. Define a break procedure that gets a polynomial. Define a procedure to get the next token or polynomial. Recursive procedure to get a defining formula. Get the BEGIN token Get the CAD DESCRIPTION tokens. Get the surface polynomial. Get the name of the surface. Get the color of the surface. Get the number of cells and create the cell sequence in the Scad. Get the BEGIN CELL DEFINITIONS tokens. Iterate over the cells. Declarations Get the indices. Get the dimension. Get the defining formula. Do the next cell. Get the END CELL DEFINITIONS tokens. Get the BEGIN CELL DISPLAY INFORMATION tokens. Iterate over the cells. Declarations Get the indices for comparison. Get the dimension for comparison. Get the vertex sequence. For zero-cells, there is only one vertex, the Position; for one- and two-cells, the number of vertices is specified in the file. Get the triangle sequence. For two-cells, the number of vertices is specified in the file; for zero- and one-cells, there are none. Do the next cell. Get the END CELL DISPLAY INFORMATION tokens. Get the END CAD DESCRIPTION tokens. Declarations Procedure to write a defining formula. Get the operator Indent unless the nesting level is 2. Write the defining formula. Write the header. Iterate over the cells, writing the indices, dimension, and defining formula. Write the end of the cell definitions block and the start of the display information block. Iterate over the cells, writing the display information. Extract some useful quantities. Write the indices and dimension. Write the vertex sequence. Write the triangle sequence if the cell has dimension 2. Do the next cell. Write the "END"s and close the file. Declarations. Ensure that the scad and mask have the same number of elements. Build the list of ropes, backwards (of course), for the menu. Get a selection from the pop-up menu. Return the selection (minus 1 so the counts start at zero), or return -1 on timeout/abort. Returns a boolean value indicating if point satisfies the qff. ΚŸ˜™J™+J™—codešΟk ˜ Kšœ˜Kšœ œ³˜ΑKšœ˜Kšœ˜Kšœ ˜ Kšœœ˜Kšœ œ˜!Kš œœœœœœ˜eKšœœA˜VK˜K˜Kšœ ˜ Kšœ œ˜#K˜K˜ K˜ Kš œ˜ Kšœ˜Kšœ˜Kšœ˜Kšœœœ˜#Kšœ œ ˜K˜—K˜šΠln œœ˜Kšœ œœ@˜WKšœ˜ Kšœ˜K˜Kš Οnœœœœœ˜&K˜š Ÿœœœœœ˜_K˜™ Kšœœœ˜Kšœ˜Kšœ˜Kšœ%˜%Kšœ$˜$K˜Kšœ˜Kšœ"˜"Kšœœ&˜BKšœœ˜K˜Kšœœ˜Kšœ œ˜$Kšœœ˜Kšœœ˜.K˜K˜—™UšŸ œœœ)˜`K˜Kšœ œ ˜1Kšœœ<˜`K˜™šœœ˜"Kšœ%˜%šœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœœ˜2Kšœœ˜%—šœ˜ Kšœ œ˜K˜Kšœœ˜Kšœ˜KšœS˜SK˜—Kš˜K˜——™ šœ˜ Kšœ'˜'Kšœ œ(˜8Kšœ œœ˜&Kšœ œ˜šœ˜Kšœ˜Kšœ˜Kšœœ˜+Kšœœ˜%—K˜Kšœ ˜ šœœ˜K˜Kšœ˜Kšœ˜—Kšœœ4˜EKšœ˜šœœœ˜Kšœ1˜1Kšœ˜Kšœ˜—šœ˜ Kšœ œ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—Kšœ˜K˜—šœ˜K˜————™$Kšœ œ˜#Kšœ9˜9Kšœ œ˜!Kšœ(˜(K™—™Kšœ œ ˜Kšœœ"˜6Kšœ˜Kšœ:˜:K˜—™/Kšœ˜Kšœœ˜%Kšœ0˜0Kšœ œ*˜8Kšœ˜K˜—™šœœœ˜1K˜™.Kšœ œ"˜3Kšœ œ˜(Kš œœ#œœ˜@K™šœœ2œ™CK™~—K™K˜™$Kšœœ$™HKšœ œ#˜IKšœ œ#˜IKšœ œ#˜IKšœ6˜6K˜—™Cšœ"™"KšœH™HKšœI™IKšœG™G—K™—™KšœP˜PK˜—™+šœ"˜,K˜šœ˜ Kšœœ˜Kšœ0œ˜RKšœ"œ"˜JKšœ%œ˜=Kšœœ˜:Kšœ"œ˜BKšœ3˜3Kšœ3˜3Kšœ3˜3šœ&˜&Kšœ ˜ Kšœ ˜ Kšœ˜K˜—Kšœ"œ˜DKšœ˜K˜—šœ˜ Kšœ0œ˜RKšœ"œ"˜JKšœ%œ˜=Kšœœ˜1Kšœ"œ*˜Ošœœœ˜$Kšœœ˜Kšœœ˜>Kšœ3˜3Kšœ3˜3Kšœ3˜3šœ&˜&Kšœ ˜ Kšœ ˜ Kšœ˜K˜—Kšœ˜—Kšœ"œ˜DKšœ˜K˜—šœ˜ Kšœœ˜ K˜%Kšœ0œ˜RKšœ"œ"˜JK˜™Kšœ˜Kšœ™šœœœ˜)Kšœ%œ˜=Kšœ=˜=Kšœ˜—Kšœ"œ*˜OKšœ0™0K˜—™K˜šœœœ˜)Kšœ%œ˜=šœœœ˜,Kšœœ˜Kšœœ˜:Kšœ3˜3Kšœ3˜3Kšœ3˜3šœ/˜/Kšœ ˜ Kšœ ˜ Kšœ˜K˜—K˜Kšœ˜—Kšœ˜K˜——™'JšœB˜BJ˜—™šœœ˜Jšœ"œ˜C—šœ˜Kšœ"œA˜fšœœœ%˜4šœ*˜*Kšœ*˜*Kšœ,˜,Kšœ)˜)K˜—Kšœ˜—K˜K˜——K™ΜKšœ˜K˜—šœ˜Kšœ˜Kšœ˜K˜———™'Kšœ ˜ šœ˜K˜———™Kšœ˜K˜———™Kšœœ&˜>šœœœ˜"Kšœ$˜$Kšœ˜—K˜—™˜Kšœ2˜2Kšœœ˜ K˜K˜Kšœ˜—K˜—Kšœ˜—K˜š Ÿ œœœœœ˜UK˜K™©K˜™ Kšœ œœœ˜0Kšœ œ˜KšŸ œœœ˜KšŸ œœœ˜KšŸœœœ˜KšŸ œœ œ˜$Kšœœ˜K˜—™+šŸœœ ˜$šœœ˜Kš œœœœœ˜!Kšœ ˜K˜—šœ˜K˜———™0šŸœœ ˜)šœœ˜Kšœœœ ˜Kšœ ˜K˜—Kšœ˜—K˜—™7š Ÿ œœœœœ˜QKšœ œ˜Kšœœ ˜3Kšœ ˜Kšœ˜K˜——™.šŸœœœ$˜IKšœœ˜Kšœ(˜(Kšœ,˜,Kšœ œ˜Kšœ˜šœ2˜8Kšœ+œ˜1—šœœ.˜9Kšœ'œ˜-—šœœ2˜=Kšœ+œ˜1—šœœ+˜6Kšœ&œ˜+—šœœ*˜5Kšœ%œ˜*—Kšœœ˜šœ œ˜Kšœœ"˜5šœ˜ Kšœ œ˜K˜Kšœœ˜Kšœ˜K˜5K˜—Kš˜—šœ˜ Kšœœ$˜:šœ'˜'Kšœ œ˜K˜#Kšœœ<˜RK˜Kšœœ˜—šœ œœ˜.Kšœ7˜7Kšœ˜—Kšœ˜ Kšœ˜—Kšœ˜K˜K˜——™šœ&˜-Kšœ˜Kšœ˜K˜——™Kšœ*œœ˜EKšœ2œœ˜MK˜—™Kšœ.œœ˜IJšœ'˜'Jšœ2˜2J˜—™Kšœ+œœ˜FJšœ˜šœ(œ˜4Jšœ œ˜J˜Jš˜—šœ˜ Jšœ œ˜Jšœ˜Jšœ˜—J™—™Kšœ,œœ˜GK˜1K˜1K˜1J™—™AKšœ,œœ˜GKšœ1˜1Kšœ œ'˜7K˜—šœ&™&Kšœ,œœ˜GKšœ+œœ˜FKšœ2œœ˜MK™—™šœœœ˜&K˜—™ Kšœ œ˜—K˜™Kšœ2œœ˜MKšœ;˜;Kšœ;˜;Kšœ;˜;K™—™Kšœ1œœ˜LKšœŸ œ˜.Kšœœœ˜*K˜'K˜—™Kšœ6œœ˜QKšœ8˜8K˜—™Kšœ˜K˜——™$Kšœ*œœ˜EKšœ+œœ˜FKšœ2œœ˜MK˜—šœ.™.Kšœ,œœ˜GKšœ+œœ˜FKšœ.œœ˜IKšœ2œœ˜MK˜—™šœœœ˜&K˜—™ Kšœ œ˜K˜—K˜™Kšœ.œœ˜IKšœ<œœ˜WKšœ<œœ˜WKšœ<œœ˜WK™—™!Kšœ-œœ˜HKšœŸ œ˜.Kšœ(œœ˜CK˜—™ššœœ˜Kšœ/œœ˜JKšœœ˜Kšœ˜K˜——™Kšœ˜K˜——šœ,™,Kšœ*œœ˜EKšœ+œœ˜FKšœ.œœ˜IKšœ2œœ˜MK˜—™#Kšœ*œœ˜EKšœ*œœ˜EKšœ2œœ˜MK˜—Kšœ˜K˜—š Ÿ œœœœ˜MK˜™ Kšœ œœœ˜9KšŸ œœœ˜K˜—™&šŸœœ.œ˜X™šœœ˜šœœœ˜5K˜K˜ Kšœœ˜—šœœ˜"Kšœ˜Kšœ˜Kšœ˜Kšœœ˜K˜———™%š œ œœœœ˜1Kšœ˜Kšœ˜K˜——™šœœ˜šœ˜K˜ K˜ Kšœ˜Kšœ#˜%—šœ œœ"˜7KšœA˜AKšœ˜—Kš˜—šœ˜ šœ˜K˜ K˜ Kšœ˜Kšœ7˜9—šœ˜K˜———Kšœ˜—K˜—™Kšœ/˜1šœ˜Kšœ ˜ Kšœ˜Kšœ2˜4—šœ œœ!œ˜IKšœœ&˜-—šœ˜K˜ K˜Kšœ˜Kšœ˜Kšœ˜—Kšœ"œ˜?K˜4K˜—™Mšœœœ˜*šœ˜˜ K˜Kšœ˜ Kšœ˜ Kšœ˜!——Kšœ)œ"˜OKšœ*˜,K˜:Kšœ˜—K™—™[Kšœ0˜2Kšœ:˜šœœœ˜ šœ˜Kšœ ˜ Kšœ˜Kšœ/˜1Kšœ0˜2Kšœ0˜2—Kšœ˜—Kšœ˜K˜——™Kšœ˜———K™™$Kšœ8˜:Kšœ-˜/Kšœ˜K˜—Kšœ˜K˜—šŸ œœœœ#œœ œ˜|K˜™ Kš œ œœœœ˜#KšœœΟtœ˜,Kšœ œ˜K˜—™?Kšœ!œœ˜IK˜—™=šœœœ˜'Kšœ#˜#Kšœ'˜'Kš œœœœœœ˜nKšœ œ(˜7Kšœ œ˜&Kšœ˜K˜——™%Kšœœ œœ˜Ušœ'˜'Kšœ ˜ Kšœ˜K˜ Kšœ˜K˜——™ZKšœœœœ˜6Kšœœ˜Kšœ˜K˜——š ŸœœœOœœ˜…šœœœ˜'Kšœ?œœ˜PKšœ˜—Kšœ˜Kšœ˜K™—š Ÿ œœ_œœ˜˜K˜K™>K™Kšœœœ˜Kšœ œ ˜K™šœ˜šœ˜ šœ˜ šœœœ#˜2Kšœ;œœœ˜PKšœ˜—Kšœœ˜ Kšœ˜—šœ˜ šœœœ#˜2Kšœ:œœœ˜NKšœ˜—Kšœœ˜Kšœ˜—Kšœœ˜K˜——šœ˜ šœ/œ˜5Kšœ(˜(Kšœ(˜(Kšœ'˜'K˜—KšœœA˜Sšœ˜Kšœœ˜'Kšœ œœ˜.Kšœœ˜'Kšœœ˜—Kšœ˜—šœ˜K˜—K˜K˜—˜K˜——Kšœ˜—…—P8yq