>;import Data.List >;import Data.Maybe >;import System.Environment >;data DxfGraphics= > DxfLine{xStart::Double, yStart::Double, xEnd::Double, yEnd::Double}| > DxfArc{xCenter::Double, yCenter::Double, radius::Double, aStart::Double, aEnd::Double}| > DxfCircle{xCenter::Double, yCenter::Double, radius::Double} deriving Show >;main=let{ > ;toPairs (x:y:s)=(x,y):(toPairs s) > ;toPairs (x:[])=[] > ;toPairs []=[] > ;toDxfPair (x,y)=((read x)::Int,y) > ;processDXF a=map toDxfPair ((toPairs.lines) a) > ;groupDXF a = groupBy (\a (b, c) -> b /= 0) a > ;filterDXF=let isGraphics x=let a=(snd.head) x in (a=="LINE"||a=="ARC"||a=="CIRCLE") in filter isGraphics > ;getDxfGraphics a=let{ > ;get::[(Int,String)]->Int->Double > ;get a i =let > getDouble s =case reads s of [(x, "")] -> Just x; _ -> Nothing > in fromMaybe 0 (getDouble (snd (fromMaybe (0,"0") (find (\(x,y)->(x==i)) a))))} > in case snd (head a) of { > ;"LINE" -> DxfLine{xStart=get a 10, yStart=get a 20, xEnd=get a 11,yEnd=get a 21} > ;"ARC" -> DxfArc{xCenter=get a 10, yCenter=get a 20, radius=get a 40, aStart=get a 50, aEnd=get a 51} > ;"CIRCLE"->DxfCircle{xCenter=get a 10, yCenter=get a 20, radius=get a 40} > } > ;toSvgPath::DxfGraphics->String > ;toSvgPath g=case g of{ > ;DxfArc x y r a1 a2->let{ > ;lage=if (abs a2-a1)>180 then 1 else 0 > }in " M "++(show (x+r*(cos (a1*pi/180))))++" "++(show (y+r*(sin (a1*pi/180))))++" A "++(show r)++","++(show r)++" 0 "++(show lage)++",1 "++(show (x+r*(cos (a2*pi/180))))++","++(show (y+r*(sin (a2*pi/180)))) > ;DxfCircle x y r ->" M "++(show (x+r))++","++(show y)++ > " A "++(show r)++","++(show r)++" 0 0,1 "++(show x)++","++(show (y+r))++ > " A "++(show r)++","++(show r)++" 0 0,1 "++(show (x-r))++","++(show y)++ > " A "++(show r)++","++(show r)++" 0 0,1 "++(show x)++","++(show (y-r))++ > " A "++(show r)++","++(show r)++" 0 0,1 "++(show (x+r))++","++(show y) > ;DxfLine x1 y1 x2 y2->" M "++(show x1)++","++(show y1)++" L "++(show x2)++","++(show y2) > } > ;toSvg::DxfGraphics->String > ;toSvg g=case g of { > ;DxfLine x1 y1 x2 y2 ->"" > ;DxfCircle x y r->"" > ;DxfArc x y r a1 a2->"" > } > ;generateSvg::[DxfGraphics]->String > ;generateSvg a=""++(foldr (++) "" (map toSvg a))++"" > ;generateSvgPath::[DxfGraphics]->String > ;generateSvgPath a="" > ;breakToCycles::[DxfGraphics]->[[DxfGraphics]] > ;breakToCycles g=let{ > ;startX (DxfLine x1 y1 x2 y2) = x1 > ;startX (DxfArc x y r a1 a2) = x+r*(cos (a1*pi/180)) > ;startX (DxfCircle x y r) = x+r > ;startY (DxfLine x1 y1 x2 y2) = y1 > ;startY (DxfArc x y r a1 a2) = y+r*(sin (a1*pi/180)) > ;startY (DxfCircle x y r) = y > ;endX (DxfArc x y r a1 a2) = x+r*(cos (a2*pi/180)) > ;endX (DxfLine x1 y1 x2 y2) = x2 > ;endX (DxfCircle x y r) = x+r > ;endY (DxfLine x1 y1 x2 y2) = y2 > ;endY (DxfArc x y r a1 a2) = y+r*(sin (a2*pi/180)) > ;endY (DxfCircle x y r) = y > ;isNext g1 g2 = (abs((startX g1)-(endX g2))<0.001) && (abs((startY g1)-(endY g2))<0.001) > } in [[]] >} in do { > ;args<-getArgs > ;if length args==0 then putStr "Nead input file\n" > else do{ > ;a<-readFile (args!!0) > ;(putStr.generateSvgPath.(map getDxfGraphics).filterDXF.groupDXF.processDXF) a; > } >}