// -*- C++ -*- //---------------------------------------------------------------------- // // Rules for computing useful intermediate quantities // //---------------------------------------------------------------------- // Compute the minimum and maximum permitted distances between the // input and output shafts. BEGINPROPAGATE(Rule0_Distances) NEEDS(dmin) NEEDS(dmax) NEEDS(inSpecification) NEEDS(outSpecification) NEEDS(d) IF((dmin == UNKNOWN || dmax == UNKNOWN || d == UNKNOWN) && (inSpecification == KNOWN) && (outSpecification == KNOWN)) THEN( { tolerancedPoint a = inSpecification(); tolerancedPoint b = outSpecification(); dmin = mindistance(a,b); dmax = maxdistance(a,b); d = distance(a,b); } ) ENDRULE //---------------------------------------------------------------------- // // Generate all designs // //---------------------------------------------------------------------- BEGINGENERATOR(Rule1_DesignLoop) NEEDS(Design) IF (Design == UNKNOWN) THEN ( listIterator itr(allDesignTypes); Design.tryAll(itr); ) ENDRULE //---------------------------------------------------------------------- // // Tests for all designs // //---------------------------------------------------------------------- // The gear must clear the sides of the box by 0.1 inch BEGINTEST(Rule2_GearHitsSide) NEEDS(Gear) NEEDS(boxWidth) NEEDS(boxLength) NEEDS(Shaft) IF((Gear == KNOWN) && (boxWidth == KNOWN) && (boxLength == KNOWN) && (Shaft == KNOWN) && (MountedOn(Gear, Shaft))) THEN ( test((Shaft().x + Gear().OuterRadius < boxWidth() - 0.1) && (Shaft().x - Gear().OuterRadius > 0.1) && (Shaft().y + Gear().OuterRadius < boxLength() - 0.1) && (Shaft().y - Gear().OuterRadius > 0.1), "Gear does not fit in the box"); ) ENDRULE //---------------------------------------------------------------------- // // Generators for OneOne designs // //---------------------------------------------------------------------- // generate i/o gears with desired ratio BEGINGENERATOR(Rule3_ioRatioLoop) NEEDS(Design) NEEDS(inoutPair) NEEDS(R) IF(((Design == OneOne || Design == OneOneOne)) && (inoutPair == UNKNOWN)) THEN(list * candidates = catalogRatiosMatchingRatio(R()); listIterator itr(*candidates); inoutPair.tryAll(itr); delete candidates; ) ENDRULE //---------------------------------------------------------------------- // // Tests for OneOne designs // //---------------------------------------------------------------------- // In the OneOne design, the sum of the pitch radii must be within the // tolerance for the inter-shaft separation. BEGINTEST(Rule4_IOGearsCantMesh) NEEDS(Design) NEEDS(inGear) NEEDS(outGear) NEEDS(dmin) NEEDS(dmax) IF((Design == OneOne) && (inGear == KNOWN) && (outGear == KNOWN) && (dmin == KNOWN) && (dmax == KNOWN)) THEN ( test((inGear().PitchRadius + outGear().PitchRadius >= dmin()) && (inGear().PitchRadius + outGear().PitchRadius <= dmax()), "input/output gears can't mesh"); ) ENDRULE //---------------------------------------------------------------------- // // Propagators for OneOne // //---------------------------------------------------------------------- // extract individual gears from the inoutPair BEGINPROPAGATE(Rule5_ioPropagate) NEEDS(inoutPair) IF( inoutPair == KNOWN) THEN ( inGear = inoutPair().g1; outGear = inoutPair().g2; ) ENDRULE // position the input and output shafts BEGINPROPAGATE(Rule6_PositionInOutOneOne) NEEDS(Design) NEEDS(inGear) NEEDS(outGear) NEEDS(inSpecification) NEEDS(outSpecification) NEEDS(in) NEEDS(out) NEEDS(d) IF((Design == OneOne) && (d == KNOWN) && (inGear == KNOWN) && (outGear == KNOWN) && (inSpecification == KNOWN) && (outSpecification == KNOWN) && (in == UNKNOWN) && (out == UNKNOWN)) THEN ( // Choose positions for in and out that are separated by dist double dist = inGear().PitchRadius + outGear().PitchRadius; // center along the line connecting inSpecification to outSpecification // and hope that the resulting points lie inside their // respective boxes. double start = 0.5 * (1.0 - dist / d()); point p = outSpecification() - inSpecification(); in = inSpecification() + start * p; out = outSpecification() - start * p; ) ENDRULE //---------------------------------------------------------------------- // // Generators for OneOneOne // //---------------------------------------------------------------------- // inoutPair's are generated using the same rule as the OneOne design // if we have values for the input and output gears but not for idler1 // try to choose a gear for idler1 BEGINGENERATOR(Rule7_GenerateIdler1Gear1) NEEDS(Design) NEEDS(inGear) NEEDS(outGear) NEEDS(idler1Gear1) IF ((Design == KNOWN) && (!(Design == OneOne)) && (inGear == KNOWN) && (outGear == KNOWN) && (idler1Gear1 == UNKNOWN)) THEN ( listIterator itr(catalog); idler1Gear1.tryAll(itr); ) ENDRULE // if we have values for input, output, and idler1gear1 // generate possible locations for idler1 BEGINGENERATOR(Rule8_GenerateIdler1) NEEDS(Design) NEEDS(in) NEEDS(out) NEEDS(inGear) NEEDS(outGear) NEEDS(idler1Gear1) NEEDS(idler1) NEEDS(d) IF ((Design == OneOneOne) && (in == KNOWN) && (out == KNOWN) && (inGear == KNOWN) && (outGear == KNOWN) && (idler1Gear1 == KNOWN) && (idler1 == UNKNOWN) && (d == KNOWN) ) THEN ({list possibleCenters; double r = idler1Gear1().PitchRadius; double a = inGear().PitchRadius + r; double b = outGear().PitchRadius + r; double c = d(); double cosIn = ((square(c) + square(a) - square(b)) / (2 * a * c)); double sinIn = sqrt(1 - square(cosIn)); double inout = a * cosIn; double inoutPerp = a * sinIn; point deltaOutIn = out() - in(); point Q = in() + (inout / c) * deltaOutIn; point temp = (inoutPerp / c) * deltaOutIn; point P(-temp.y, temp.x); // rotate by 90 degrees possibleCenters.add(Q + P); possibleCenters.add(Q - P); cout << "Possible centers for this gear are " << possibleCenters << endl; listIterator itr(possibleCenters); idler1.tryAll(itr); } ) ENDRULE //---------------------------------------------------------------------- // // Propagators for OneOneOne designs // //---------------------------------------------------------------------- // Position the input and output shafts at their nominal locations BEGINPROPAGATE(Rule9_PositionInOut) NEEDS(Design) NEEDS(inSpecification) NEEDS(outSpecification) NEEDS(in) NEEDS(out) IF((Design == KNOWN) && (!(Design == OneOne)) && (in == UNKNOWN) && (out == UNKNOWN) && (inSpecification == KNOWN) && (outSpecification == KNOWN)) THEN ( in = inSpecification(); out = outSpecification(); ) ENDRULE //---------------------------------------------------------------------- // // Tests for OneOneOne designs // //---------------------------------------------------------------------- // In the OneOneOne design, the sum of the outer radii must be less // than the distance between the two shafts; otherwise the gears will collide BEGINTEST(Rule10_IOGearTooSmall) NEEDS(Design) NEEDS(inGear) NEEDS(outGear) NEEDS(dmin) NEEDS(in) NEEDS(out) IF((Design == OneOneOne) && (inGear == KNOWN) && (outGear == KNOWN) && (dmin == KNOWN) && (in == KNOWN ) && (out == KNOWN)) THEN ( test(inGear().OuterRadius + outGear().OuterRadius < d(), "input/output gears will collide"); ) ENDRULE // if we have values for input, output, and idler1gear1, then check // whether the idler1gear1 is big enough to reach both of the other gears BEGINTEST(Rule11_IdlerGearMustReach) NEEDS(Design) NEEDS(inGear) NEEDS(outGear) NEEDS(idler1Gear1) NEEDS(d) IF ((Design == OneOneOne) && (inGear == KNOWN) && (outGear == KNOWN) && (idler1Gear1 == KNOWN) && (d == KNOWN) ) THEN ( test(inGear().PitchRadius + (2 * idler1Gear1().PitchRadius) + outGear().PitchRadius >= d(), "idler1Gear1 is too small to reach the input and output gears."); ) ENDRULE //---------------------------------------------------------------------- // // Generators for OneTwoOne designs // //---------------------------------------------------------------------- // We generate 4-tuples of gears with the desired ratios and then // check for various problems. BEGINGENERATOR(Rule12_GenerateQuadChains) NEEDS(Design) NEEDS(quadChain) NEEDS(R) IF( (Design == OneTwoOne) && (R == KNOWN) && (quadChain == UNKNOWN) ) THEN( list * quads = catalogQuadruplesMatchingRatio(R()); listIterator itr(*quads); quadChain.tryAll(itr); delete quads; ) ENDRULE BEGINGENERATOR(Rule13_PositionIdlerOneTwoOne) NEEDS(Design) NEEDS(inGear) NEEDS(outGear) NEEDS(idler1Gear1) NEEDS(idler1Gear2) NEEDS(in) NEEDS(out) NEEDS(d) IF((Design == OneTwoOne) && (in == KNOWN) && (out == KNOWN) && (inGear == KNOWN) && (outGear == KNOWN) && (idler1Gear1 == KNOWN) && (idler1Gear2 == KNOWN) && (idler1 == UNKNOWN) && (d == KNOWN) ) THEN ( list possibleCenters; double a = inGear().PitchRadius + idler1Gear1().PitchRadius; double b = outGear().PitchRadius + idler1Gear2().PitchRadius; double c = d(); double cosIn = ((square(c) + square(a) - square(b)) / (2 * a * c)); double sinIn = sqrt(1 - square(cosIn)); double inout = a * cosIn; double inoutPerp = a * sinIn; point deltaOutIn = out() - in(); point Q = in() + (inout / c) * deltaOutIn; point temp = (inoutPerp / c) * deltaOutIn; point P(-temp.y, temp.x); // rotate by 90 degrees possibleCenters.add(Q + P); possibleCenters.add(Q - P); cout << "Possible centers for this shaft are " << possibleCenters << endl; listIterator itr(possibleCenters); idler1.tryAll(itr); ) ENDRULE //---------------------------------------------------------------------- // // Propagators for OneTwoOne designs // //---------------------------------------------------------------------- BEGINPROPAGATE(Rule14_PropagateQuad) NEEDS(Design) NEEDS(quadChain) IF( (Design == OneTwoOne) && (quadChain == KNOWN)) THEN ( inGear = quadChain().gear1(); idler1Gear1 = quadChain().gear2(); idler1Gear2 = quadChain().gear3(); outGear = quadChain().gear4(); ) ENDRULE //---------------------------------------------------------------------- // // Tests for OneTwoOne designs // //---------------------------------------------------------------------- // test for collisions // inGear and idler1Gear1 could hit out // outGear and idler1Gear2 could hit in // We can test for the inGear and outGear collisions before // positioning the idler1 shaft. BEGINTEST(Rule15_ioGearsHitioShafts) NEEDS(Design) NEEDS(inGear) NEEDS(outGear) NEEDS(d) IF( (Design == OneTwoOne) && (inGear == KNOWN) && (outGear == KNOWN) && (d == KNOWN)) THEN ( test(d() - (0.05 + 0.125) > inGear().OuterRadius, "inGear hits out shaft"); test(d() - (0.05 + 0.125) > outGear().OuterRadius, "outGear hits in shaft"); ) ENDRULE BEGINTEST(Rule16_idlerGear2HitsIn) NEEDS(Design) NEEDS(in) NEEDS(idler1Gear2) NEEDS(idler1) IF((Design == OneTwoOne) && (in == KNOWN) && (idler1Gear2 == KNOWN) && (idler1 == KNOWN)) THEN ( test(distance(in(), idler1()) - (0.05 + 0.125) > idler1Gear2().OuterRadius, "idlerGear2 hits in shaft"); ) ENDRULE BEGINTEST(Rule17_idlerGear1HitsOut) NEEDS(Design) NEEDS(out) NEEDS(idler1Gear1) NEEDS(idler1) IF((Design == OneTwoOne) && (out == KNOWN) && (idler1Gear1 == KNOWN) && (idler1 == KNOWN)) THEN ( test(distance(out(), idler1()) - (0.05 + 0.125) > idler1Gear1().OuterRadius, "idlerGear1 hits out shaft"); ) ENDRULE BEGINTEST(Rule18_idlerGearsBigEnough) NEEDS(Design) NEEDS(inGear) NEEDS(outGear) NEEDS(idler1Gear1) NEEDS(idler1Gear2) NEEDS(d) IF ((Design == OneTwoOne) && (inGear == KNOWN) && (outGear == KNOWN) && (idler1Gear1 == KNOWN) && (idler1Gear2 == KNOWN) && (d == KNOWN)) THEN ( test(inGear().PitchRadius + idler1Gear1().PitchRadius + idler1Gear2().PitchRadius + outGear().PitchRadius - (0.05 + 0.125) >= d(), "idler gears too small to reach from in to out"); ) ENDRULE