PrithviGuardian / client /src /lib /roadDesignCalculator.ts
Varad Bakshi
Fresh upload
e7427b5
Raw
History Blame Contribute Delete
13.9 kB
// 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 };