Spaces:
Configuration error
Configuration error
| // MargYantra – Road Design Tool | |
| // IRC standards-based calculations for superelevation, camber, and transition curves | |
| interface RoadDesignInput { | |
| road_type: 'highway' | 'arterial' | 'collector' | 'local' | 'expressway'; | |
| design_speed: number; // km/h | |
| curve_radius: number; // meters | |
| cross_slope: number; // percentage | |
| terrain: 'plain' | 'rolling' | 'mountainous'; | |
| pavement_type: 'flexible' | 'rigid' | 'composite'; | |
| } | |
| interface RoadDesignOutput { | |
| superelevation: number; // percentage | |
| camber: number; // percentage | |
| transition_length: number; // meters | |
| sight_distance: number; // meters | |
| widening_required: number; // meters | |
| banking_angle: number; // degrees | |
| design_considerations: string[]; | |
| irc_references: string[]; | |
| safety_warnings: string[]; | |
| confidence: number; | |
| } | |
| class RoadDesignCalculator { | |
| private readonly MAX_SUPERELEVATION = 7.0; // IRC standard maximum | |
| private readonly MIN_CURVE_RADIUS = 30; // minimum for any road | |
| private readonly MAX_DESIGN_SPEED = 120; // km/h for highways | |
| // IRC standard values for different road types | |
| private roadStandards = new Map([ | |
| ['highway', { | |
| max_speed: 100, | |
| min_radius: 230, | |
| camber_flexible: 2.5, | |
| camber_rigid: 2.0, | |
| lane_width: 3.5 | |
| }], | |
| ['arterial', { | |
| max_speed: 80, | |
| min_radius: 120, | |
| camber_flexible: 2.5, | |
| camber_rigid: 2.0, | |
| lane_width: 3.5 | |
| }], | |
| ['collector', { | |
| max_speed: 65, | |
| min_radius: 80, | |
| camber_flexible: 3.0, | |
| camber_rigid: 2.5, | |
| lane_width: 3.25 | |
| }], | |
| ['local', { | |
| max_speed: 50, | |
| min_radius: 50, | |
| camber_flexible: 3.0, | |
| camber_rigid: 2.5, | |
| lane_width: 3.0 | |
| }], | |
| ['expressway', { | |
| max_speed: 120, | |
| min_radius: 360, | |
| camber_flexible: 2.0, | |
| camber_rigid: 1.7, | |
| lane_width: 3.75 | |
| }] | |
| ]); | |
| calculateRoadDesign(input: RoadDesignInput): RoadDesignOutput { | |
| try { | |
| // Validate inputs | |
| this.validateInputs(input); | |
| const roadStd = this.roadStandards.get(input.road_type); | |
| if (!roadStd) { | |
| throw new Error(`Unknown road type: ${input.road_type}`); | |
| } | |
| // Calculate superelevation | |
| const superelevation = this.calculateSuperelevation(input.design_speed, input.curve_radius); | |
| // Determine camber | |
| const camber = this.calculateCamber(input.pavement_type, input.road_type); | |
| // Calculate transition curve length | |
| const transitionLength = this.calculateTransitionLength(input.design_speed, input.curve_radius, superelevation); | |
| // Calculate sight distance | |
| const sightDistance = this.calculateSightDistance(input.design_speed, input.curve_radius); | |
| // Calculate mechanical widening | |
| const widening = this.calculateWidening(input.curve_radius, roadStd.lane_width); | |
| // Convert superelevation to banking angle | |
| const bankingAngle = Math.atan(superelevation / 100) * (180 / Math.PI); | |
| // Generate design considerations and warnings | |
| const designConsiderations = this.getDesignConsiderations(input, superelevation, transitionLength); | |
| const safetyWarnings = this.getSafetyWarnings(input, superelevation, sightDistance); | |
| const ircReferences = this.getIRCReferences(input.road_type); | |
| // Calculate confidence based on design adequacy | |
| const confidence = this.calculateConfidence(input, superelevation, sightDistance); | |
| return { | |
| superelevation: Math.round(superelevation * 100) / 100, | |
| camber: camber, | |
| transition_length: Math.round(transitionLength), | |
| sight_distance: Math.round(sightDistance), | |
| widening_required: Math.round(widening * 100) / 100, | |
| banking_angle: Math.round(bankingAngle * 100) / 100, | |
| design_considerations: designConsiderations, | |
| irc_references: ircReferences, | |
| safety_warnings: safetyWarnings, | |
| confidence: confidence | |
| }; | |
| } catch (error) { | |
| throw new Error(`Road design calculation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); | |
| } | |
| } | |
| private validateInputs(input: RoadDesignInput): void { | |
| if (!input.road_type || !this.roadStandards.has(input.road_type)) { | |
| throw new Error('Invalid road type. Must be one of: highway, arterial, collector, local, expressway'); | |
| } | |
| if (!input.design_speed || input.design_speed <= 0 || input.design_speed > this.MAX_DESIGN_SPEED) { | |
| throw new Error(`Design speed must be between 1 and ${this.MAX_DESIGN_SPEED} km/h`); | |
| } | |
| if (!input.curve_radius || input.curve_radius < this.MIN_CURVE_RADIUS) { | |
| throw new Error(`Curve radius must be at least ${this.MIN_CURVE_RADIUS} meters`); | |
| } | |
| if (input.cross_slope !== undefined && (input.cross_slope < -10 || input.cross_slope > 10)) { | |
| throw new Error('Cross slope must be between -10% and +10%'); | |
| } | |
| if (!input.terrain || !['plain', 'rolling', 'mountainous'].includes(input.terrain)) { | |
| throw new Error('Invalid terrain type. Must be one of: plain, rolling, mountainous'); | |
| } | |
| if (!input.pavement_type || !['flexible', 'rigid', 'composite'].includes(input.pavement_type)) { | |
| throw new Error('Invalid pavement type. Must be one of: flexible, rigid, composite'); | |
| } | |
| } | |
| private calculateSuperelevation(speed: number, radius: number): number { | |
| // IRC 73-1980 formula for superelevation | |
| // e = V²/(127R) - f, where f = lateral friction coefficient | |
| const lateralFriction = this.getLateralFrictionCoefficient(speed); | |
| const superelevation = (speed * speed) / (127 * radius) - lateralFriction; | |
| // Apply IRC limits | |
| if (superelevation < 0) return 0; | |
| if (superelevation > this.MAX_SUPERELEVATION) return this.MAX_SUPERELEVATION; | |
| return superelevation; | |
| } | |
| private getLateralFrictionCoefficient(speed: number): number { | |
| // IRC 73-1980 values for lateral friction | |
| if (speed <= 50) return 0.15; | |
| if (speed <= 65) return 0.14; | |
| if (speed <= 80) return 0.13; | |
| if (speed <= 100) return 0.12; | |
| return 0.10; | |
| } | |
| private calculateCamber(pavementType: string, roadType: string): number { | |
| const roadStd = this.roadStandards.get(roadType); | |
| if (!roadStd) return 2.5; | |
| switch (pavementType) { | |
| case 'flexible': | |
| return roadStd.camber_flexible; | |
| case 'rigid': | |
| return roadStd.camber_rigid; | |
| case 'composite': | |
| return (roadStd.camber_flexible + roadStd.camber_rigid) / 2; | |
| default: | |
| return 2.5; | |
| } | |
| } | |
| private calculateTransitionLength(speed: number, radius: number, superelevation: number): number { | |
| // IRC 73-1980 formula for transition curve length | |
| // L = 0.0215 * V³ / R (minimum formula) | |
| // Also consider superelevation development length | |
| const minLength = (0.0215 * speed * speed * speed) / radius; | |
| const superelevationLength = speed * superelevation / 0.5; // 0.5% per meter development rate | |
| return Math.max(minLength, superelevationLength, 30); // minimum 30m | |
| } | |
| private calculateSightDistance(speed: number, radius: number): number { | |
| // IRC SP 73-2018 stopping sight distance | |
| const reactionTime = 2.5; // seconds | |
| const brakingEfficiency = 0.35; // for wet roads | |
| const grade = 0; // assuming level road | |
| const reactionDistance = (speed * 1000 / 3600) * reactionTime; | |
| const brakingDistance = (speed * speed) / (254 * (brakingEfficiency + grade / 100)); | |
| const stoppingSightDistance = reactionDistance + brakingDistance; | |
| // Check if horizontal curve affects sight distance | |
| const availableSightDistance = this.calculateHorizontalSightDistance(radius); | |
| return Math.min(stoppingSightDistance, availableSightDistance); | |
| } | |
| private calculateHorizontalSightDistance(radius: number): number { | |
| // For horizontal curves, sight distance is limited by curve geometry | |
| const middleOrdinate = 1.5; // typical clearance from centerline | |
| return 2 * Math.sqrt(2 * radius * middleOrdinate - middleOrdinate * middleOrdinate); | |
| } | |
| private calculateWidening(radius: number, laneWidth: number): number { | |
| // IRC SP 73-2018 mechanical widening formula | |
| const vehicleLength = 6; // meters (design vehicle) | |
| const wheelBase = 3.5; // meters | |
| const widening = (vehicleLength * vehicleLength) / (2 * radius) + (wheelBase * wheelBase) / (2 * radius); | |
| return Math.max(0, widening); | |
| } | |
| private getDesignConsiderations(input: RoadDesignInput, superelevation: number, transitionLength: number): string[] { | |
| const considerations: string[] = []; | |
| if (superelevation > 5.0) { | |
| considerations.push('High superelevation - ensure proper drainage design'); | |
| } | |
| if (transitionLength > 200) { | |
| considerations.push('Long transition curve - check for adequate sight distance'); | |
| } | |
| if (input.terrain === 'mountainous') { | |
| considerations.push('Mountainous terrain - consider additional safety measures and escape ramps'); | |
| } | |
| if (input.design_speed > 80) { | |
| considerations.push('High speed design - implement enhanced safety features'); | |
| } | |
| considerations.push('Ensure proper signage and pavement markings as per IRC 35'); | |
| considerations.push('Consider weather conditions and seasonal variations'); | |
| return considerations; | |
| } | |
| private getSafetyWarnings(input: RoadDesignInput, superelevation: number, sightDistance: number): string[] { | |
| const warnings: string[] = []; | |
| const roadStd = this.roadStandards.get(input.road_type); | |
| if (input.curve_radius < (roadStd?.min_radius || 100)) { | |
| warnings.push(`Curve radius below recommended minimum for ${input.road_type} roads`); | |
| } | |
| if (superelevation === this.MAX_SUPERELEVATION) { | |
| warnings.push('Maximum superelevation reached - consider increasing curve radius'); | |
| } | |
| if (sightDistance < this.getMinimumSightDistance(input.design_speed)) { | |
| warnings.push('Inadequate sight distance - reduce design speed or increase radius'); | |
| } | |
| if (input.design_speed > (roadStd?.max_speed || 50)) { | |
| warnings.push('Design speed exceeds recommended maximum for this road type'); | |
| } | |
| return warnings; | |
| } | |
| private getMinimumSightDistance(speed: number): number { | |
| // IRC minimum sight distance requirements | |
| return speed * 2; // simplified minimum requirement | |
| } | |
| private getIRCReferences(roadType: string): string[] { | |
| const references = [ | |
| 'IRC 73-1980: Geometric Design Standards for Rural Highways', | |
| 'IRC SP 73-2018: Manual of Specifications & Standards for Four Laning of Highways', | |
| 'IRC 35-2015: Code of Practice for Road Markings', | |
| 'IRC 103-2012: Guidelines for Pedestrian Facilities' | |
| ]; | |
| if (roadType === 'expressway') { | |
| references.push('IRC 5-2015: Standard Specifications and Code of Practice for Road Bridges'); | |
| } | |
| return references; | |
| } | |
| private calculateConfidence(input: RoadDesignInput, superelevation: number, sightDistance: number): number { | |
| let confidence = 90; | |
| const roadStd = this.roadStandards.get(input.road_type); | |
| // Reduce confidence for edge cases | |
| if (input.curve_radius < (roadStd?.min_radius || 100) * 1.2) { | |
| confidence -= 15; | |
| } | |
| if (superelevation > 6.0) { | |
| confidence -= 10; | |
| } | |
| if (sightDistance < this.getMinimumSightDistance(input.design_speed) * 1.1) { | |
| confidence -= 20; | |
| } | |
| return Math.max(50, confidence); | |
| } | |
| // Helper method to get design speed recommendations | |
| getDesignSpeedRecommendations(): Record<string, { recommended: number; maximum: number }> { | |
| return { | |
| 'expressway': { recommended: 100, maximum: 120 }, | |
| 'highway': { recommended: 80, maximum: 100 }, | |
| 'arterial': { recommended: 65, maximum: 80 }, | |
| 'collector': { recommended: 50, maximum: 65 }, | |
| 'local': { recommended: 40, maximum: 50 } | |
| }; | |
| } | |
| // Method to check design adequacy | |
| checkDesignAdequacy(input: RoadDesignInput): { adequate: boolean; issues: string[] } { | |
| const issues: string[] = []; | |
| const roadStd = this.roadStandards.get(input.road_type); | |
| if (!roadStd) { | |
| return { adequate: false, issues: ['Invalid road type'] }; | |
| } | |
| if (input.design_speed > roadStd.max_speed) { | |
| issues.push(`Design speed exceeds maximum for ${input.road_type} (${roadStd.max_speed} km/h)`); | |
| } | |
| if (input.curve_radius < roadStd.min_radius) { | |
| issues.push(`Curve radius below minimum for ${input.road_type} (${roadStd.min_radius}m)`); | |
| } | |
| return { | |
| adequate: issues.length === 0, | |
| issues | |
| }; | |
| } | |
| // Generate detailed design report | |
| generateDesignReport(input: RoadDesignInput, output: RoadDesignOutput): string { | |
| return ` | |
| ROAD GEOMETRIC DESIGN REPORT | |
| =========================== | |
| INPUT PARAMETERS: | |
| - Road Type: ${input.road_type} | |
| - Design Speed: ${input.design_speed} km/h | |
| - Curve Radius: ${input.curve_radius} m | |
| - Cross Slope: ${input.cross_slope}% | |
| - Terrain: ${input.terrain} | |
| - Pavement Type: ${input.pavement_type} | |
| DESIGN RESULTS: | |
| - Superelevation: ${output.superelevation}% | |
| - Camber: ${output.camber}% | |
| - Transition Length: ${output.transition_length} m | |
| - Sight Distance: ${output.sight_distance} m | |
| - Widening Required: ${output.widening_required} m | |
| - Banking Angle: ${output.banking_angle}° | |
| DESIGN CONSIDERATIONS: | |
| ${output.design_considerations.map(c => `- ${c}`).join('\n')} | |
| SAFETY WARNINGS: | |
| ${output.safety_warnings.map(w => `- ${w}`).join('\n')} | |
| IRC REFERENCES: | |
| ${output.irc_references.map(ref => `- ${ref}`).join('\n')} | |
| Design Confidence: ${output.confidence}% | |
| Generated by Prithvi Guardian AI - MargYantra Module | |
| Date: ${new Date().toLocaleDateString('en-IN')} | |
| `; | |
| } | |
| } | |
| export const roadDesignCalculator = new RoadDesignCalculator(); | |
| export { RoadDesignInput, RoadDesignOutput }; |