// adds a circle the existing list; if 'hole' is true the contour is // a hole. Returns true if OK. bool VRML_LAYER::AddCircle( double x, double y, double rad, int csides, bool hole ) { int pad = NewContour(); if( pad < 0 ) { error = "AddCircle(): failed to add a contour"; return false; } if( csides < 6 ) csides = CalcNSides( rad, maxdev ); // even numbers give prettier results if( csides & 1 ) csides += 1; double da = M_PI * 2.0 / csides; bool fail = false; if( hole ) { for( double angle = 0; angle < M_PI * 2; angle += da ) fail |= !AddVertex( pad, x + rad * cos( angle ), y - rad * sin( angle ) ); } else { for( double angle = 0; angle < M_PI * 2; angle += da ) fail |= !AddVertex( pad, x + rad * cos( angle ), y + rad * sin( angle ) ); } return !fail; }
// adds a circle the existing list; if 'hole' is true the contour is // a hole. Returns true if OK. bool VRML_LAYER::AddCircle( double aXpos, double aYpos, double aRadius, bool aHoleFlag, bool aPlatedHole ) { int pad; if( aHoleFlag && aPlatedHole ) pad = NewContour( true ); else pad = NewContour( false ); if( pad < 0 ) { error = "AddCircle(): failed to add a contour"; return false; } return AppendCircle( aXpos, aYpos, aRadius, pad, aHoleFlag ); }
// adds an arc with the given center, start point, pen width, and angle (degrees). bool VRML_LAYER::AddArc( double aCenterX, double aCenterY, double aStartX, double aStartY, double aArcWidth, double aAngle, bool aHoleFlag, bool aPlatedHole ) { aAngle *= M_PI / 180.0; // we don't accept small angles; in fact, 1 degree ( 0.01745 ) is already // way too small but we must set a limit somewhere if( aAngle < 0.01745 && aAngle > -0.01745 ) { error = "AddArc(): angle is too small: abs( angle ) < 1 degree"; return false; } double rad = sqrt( (aStartX - aCenterX) * (aStartX - aCenterX) + (aStartY - aCenterY) * (aStartY - aCenterY) ); aArcWidth /= 2.0; // this is the radius of the caps // we will not accept an arc with an inner radius close to zero so we // set a limit here. the end result will vary somewhat depending on // the output units if( aArcWidth >= ( rad * 1.01 ) ) { error = "AddArc(): width/2 exceeds radius*1.01"; return false; } // calculate the radii of the outer and inner arcs double orad = rad + aArcWidth; double irad = rad - aArcWidth; int osides = calcNSides( orad, aAngle ); int isides = calcNSides( irad, aAngle ); int csides = calcNSides( aArcWidth, M_PI ); double stAngle = atan2( aStartY - aCenterY, aStartX - aCenterX ); double endAngle = stAngle + aAngle; // calculate ends of inner and outer arc double oendx = aCenterX + orad* cos( endAngle ); double oendy = aCenterY + orad* sin( endAngle ); double ostx = aCenterX + orad* cos( stAngle ); double osty = aCenterY + orad* sin( stAngle ); double iendx = aCenterX + irad* cos( endAngle ); double iendy = aCenterY + irad* sin( endAngle ); double istx = aCenterX + irad* cos( stAngle ); double isty = aCenterY + irad* sin( stAngle ); if( ( aAngle < 0 && !aHoleFlag ) || ( aAngle > 0 && aHoleFlag ) ) { aAngle = -aAngle; std::swap( stAngle, endAngle ); std::swap( oendx, ostx ); std::swap( oendy, osty ); std::swap( iendx, istx ); std::swap( iendy, isty ); } int arc; if( aHoleFlag && aPlatedHole ) arc = NewContour( true ); else arc = NewContour( false ); if( arc < 0 ) { error = "AddArc(): could not create a contour"; return false; } // trace the outer arc: int i; double ang; double da = aAngle / osides; for( ang = stAngle, i = 0; i < osides; ang += da, ++i ) AddVertex( arc, aCenterX + orad * cos( ang ), aCenterY + orad * sin( ang ) ); // trace the first cap double capx = ( iendx + oendx ) / 2.0; double capy = ( iendy + oendy ) / 2.0; if( aHoleFlag ) da = -M_PI / csides; else da = M_PI / csides; for( ang = endAngle, i = 0; i < csides; ang += da, ++i ) AddVertex( arc, capx + aArcWidth * cos( ang ), capy + aArcWidth * sin( ang ) ); // trace the inner arc: da = -aAngle / isides; for( ang = endAngle, i = 0; i < isides; ang += da, ++i ) AddVertex( arc, aCenterX + irad * cos( ang ), aCenterY + irad * sin( ang ) ); // trace the final cap capx = ( istx + ostx ) / 2.0; capy = ( isty + osty ) / 2.0; if( aHoleFlag ) da = -M_PI / csides; else da = M_PI / csides; for( ang = stAngle + M_PI, i = 0; i < csides; ang += da, ++i ) AddVertex( arc, capx + aArcWidth * cos( ang ), capy + aArcWidth * sin( ang ) ); return true; }
// adds a slotted pad with orientation given by angle; if 'hole' is true the // contour is a hole. Returns true if OK. bool VRML_LAYER::AddSlot( double aCenterX, double aCenterY, double aSlotLength, double aSlotWidth, double aAngle, bool aHoleFlag, bool aPlatedHole ) { aAngle *= M_PI / 180.0; if( aSlotWidth > aSlotLength ) { aAngle += M_PI2; std::swap( aSlotLength, aSlotWidth ); } aSlotWidth /= 2.0; aSlotLength = aSlotLength / 2.0 - aSlotWidth; int csides = calcNSides( aSlotWidth, M_PI ); double capx, capy; capx = aCenterX + cos( aAngle ) * aSlotLength; capy = aCenterY + sin( aAngle ) * aSlotLength; double ang, da; int i; int pad; if( aHoleFlag && aPlatedHole ) pad = NewContour( true ); else pad = NewContour( false ); if( pad < 0 ) { error = "AddCircle(): failed to add a contour"; return false; } da = M_PI / csides; bool fail = false; if( aHoleFlag ) { for( ang = aAngle + M_PI2, i = 0; i < csides; ang -= da, ++i ) fail |= !AddVertex( pad, capx + aSlotWidth * cos( ang ), capy + aSlotWidth * sin( ang ) ); ang = aAngle - M_PI2; fail |= !AddVertex( pad, capx + aSlotWidth * cos( ang ), capy + aSlotWidth * sin( ang ) ); capx = aCenterX - cos( aAngle ) * aSlotLength; capy = aCenterY - sin( aAngle ) * aSlotLength; for( ang = aAngle - M_PI2, i = 0; i < csides; ang -= da, ++i ) fail |= !AddVertex( pad, capx + aSlotWidth * cos( ang ), capy + aSlotWidth * sin( ang ) ); ang = aAngle + M_PI2; fail |= !AddVertex( pad, capx + aSlotWidth * cos( ang ), capy + aSlotWidth * sin( ang ) ); } else { for( ang = aAngle - M_PI2, i = 0; i < csides; ang += da, ++i ) fail |= !AddVertex( pad, capx + aSlotWidth * cos( ang ), capy + aSlotWidth * sin( ang ) ); ang = aAngle + M_PI2; fail |= !AddVertex( pad, capx + aSlotWidth * cos( ang ), capy + aSlotWidth * sin( ang ) ); capx = aCenterX - cos( aAngle ) * aSlotLength; capy = aCenterY - sin( aAngle ) * aSlotLength; for( ang = aAngle + M_PI2, i = 0; i < csides; ang += da, ++i ) fail |= !AddVertex( pad, capx + aSlotWidth * cos( ang ), capy + aSlotWidth * sin( ang ) ); ang = aAngle - M_PI2; fail |= !AddVertex( pad, capx + aSlotWidth * cos( ang ), capy + aSlotWidth * sin( ang ) ); } return !fail; }
// adds an arc with the given center, start point, pen width, and angle. bool VRML_LAYER::AddArc( double cx, double cy, double startx, double starty, double width, double angle, int csides, bool hole ) { // we don't accept small angles; in fact, 1 degree ( 0.01745 ) is already // way too small but we must set a limit somewhere if( angle < 0.01745 && angle > -0.01745 ) { error = "AddArc(): angle is too small: abs( angle ) < 0.01745"; return false; } double rad = sqrt( (startx - cx) * (startx - cx) + (starty - cy) * (starty - cy) ); width /= 2.0; // this is the radius of the caps // we will not accept an arc with an inner radius close to zero so we // set a limit here. the end result will vary somewhat depending on // the output units if( width >= ( rad * 1.01 ) ) { error = "AddArc(): width/2 exceeds radius*1.01"; return false; } // calculate the radii of the outer and inner arcs double orad = rad + width; double irad = rad - width; int osides = csides * angle / ( M_PI * 2.0 ); int isides = csides * angle / ( M_PI * 2.0 ); if( osides < 0 ) osides = -osides; if( osides < 3 ) { osides = CalcNSides( orad, maxdev ) * angle / ( M_PI * 2.0 ); if( osides < 0 ) osides = -osides; if( osides < 3 ) osides = 3; } if( isides < 0 ) isides = -isides; if( isides < 3 ) { isides = CalcNSides( irad, maxdev ) * angle / ( M_PI * 2.0 ); if( isides < 0 ) isides = -isides; if( isides < 3 ) isides = 3; } if( csides < 6 ) csides = CalcNSides( width, maxdev ); if( csides & 1 ) csides += 1; csides /= 2; double stAngle = atan2( starty - cy, startx - cx ); double endAngle = stAngle + angle; // calculate ends of inner and outer arc double oendx = cx + orad* cos( endAngle ); double oendy = cy + orad* sin( endAngle ); double ostx = cx + orad* cos( stAngle ); double osty = cy + orad* sin( stAngle ); double iendx = cx + irad* cos( endAngle ); double iendy = cy + irad* sin( endAngle ); double istx = cx + irad* cos( stAngle ); double isty = cy + irad* sin( stAngle ); if( ( angle < 0 && !hole ) || ( angle > 0 && hole ) ) { angle = -angle; std::swap( stAngle, endAngle ); std::swap( oendx, ostx ); std::swap( oendy, osty ); std::swap( iendx, istx ); std::swap( iendy, isty ); } int arc = NewContour(); if( arc < 0 ) { error = "AddArc(): could not create a contour"; return false; } // trace the outer arc: int i; double ang; double da = angle / osides; for( ang = stAngle, i = 0; i < osides; ang += da, ++i ) AddVertex( arc, cx + orad * cos( ang ), cy + orad * sin( ang ) ); // trace the first cap double capx = ( iendx + oendx ) / 2.0; double capy = ( iendy + oendy ) / 2.0; if( hole ) da = -M_PI / csides; else da = M_PI / csides; for( ang = endAngle + da, i = 2; i < csides; ang += da, ++i ) AddVertex( arc, capx + width * cos( ang ), capy + width * sin( ang ) ); // trace the inner arc: da = -angle / isides; for( ang = endAngle, i = 0; i < isides; ang += da, ++i ) AddVertex( arc, cx + irad * cos( ang ), cy + irad * sin( ang ) ); // trace the final cap capx = ( istx + ostx ) / 2.0; capy = ( isty + osty ) / 2.0; if( hole ) da = -M_PI / csides; else da = M_PI / csides; for( ang = stAngle + M_PI + da, i = 2; i < csides; ang += da, ++i ) AddVertex( arc, capx + width * cos( ang ), capy + width * sin( ang ) ); return true; }
// adds a slotted pad with orientation given by angle; if 'hole' is true the // contour is a hole. Returns true if OK. bool VRML_LAYER::AddSlot( double cx, double cy, double length, double width, double angle, int csides, bool hole ) { if( width > length ) { angle += M_PI2; std::swap( length, width ); } width /= 2.0; length = length / 2.0 - width; if( csides < 6 ) csides = CalcNSides( width, maxdev ); if( csides & 1 ) csides += 1; csides /= 2; double capx, capy; capx = cx + cos( angle ) * length; capy = cy + sin( angle ) * length; double ang, da; int i; int pad = NewContour(); if( pad < 0 ) { error = "AddCircle(): failed to add a contour"; return false; } da = M_PI / csides; bool fail = false; if( hole ) { for( ang = angle + M_PI2, i = 0; i < csides; ang -= da, ++i ) fail |= !AddVertex( pad, capx + width * cos( ang ), capy + width * sin( ang ) ); ang = angle - M_PI2; fail |= !AddVertex( pad, capx + width * cos( ang ), capy + width * sin( ang ) ); capx = cx - cos( angle ) * length; capy = cy - sin( angle ) * length; for( ang = angle - M_PI2, i = 0; i < csides; ang -= da, ++i ) fail |= !AddVertex( pad, capx + width * cos( ang ), capy + width * sin( ang ) ); ang = angle + M_PI2; fail |= !AddVertex( pad, capx + width * cos( ang ), capy + width * sin( ang ) ); } else { for( ang = angle - M_PI2, i = 0; i < csides; ang += da, ++i ) fail |= !AddVertex( pad, capx + width * cos( ang ), capy + width * sin( ang ) ); ang = angle + M_PI2; fail |= !AddVertex( pad, capx + width * cos( ang ), capy + width * sin( ang ) ); capx = cx - cos( angle ) * length; capy = cy - sin( angle ) * length; for( ang = angle + M_PI2, i = 0; i < csides; ang += da, ++i ) fail |= !AddVertex( pad, capx + width * cos( ang ), capy + width * sin( ang ) ); ang = angle - M_PI2; fail |= !AddVertex( pad, capx + width * cos( ang ), capy + width * sin( ang ) ); } return !fail; }