2022-11-06 01:33:32 +01:00
"use strict" ;
2024-02-09 11:34:23 +01:00
function _typeof ( obj ) { "@babel/helpers - typeof" ; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol . iterator ? function ( obj ) { return typeof obj ; } : function ( obj ) { return obj && "function" == typeof Symbol && obj . constructor === Symbol && obj !== Symbol . prototype ? "symbol" : typeof obj ; } , _typeof ( obj ) ; }
2022-11-06 01:33:32 +01:00
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
2024-02-09 11:34:23 +01:00
exports . piecewiseToPaths = exports [ "default" ] = void 0 ;
2022-11-06 01:33:32 +01:00
var _vecks = require ( "vecks" ) ;
var _entityToPolyline = _interopRequireDefault ( require ( "./entityToPolyline" ) ) ;
var _denormalise = _interopRequireDefault ( require ( "./denormalise" ) ) ;
var _getRGBForEntity = _interopRequireDefault ( require ( "./getRGBForEntity" ) ) ;
var _logger = _interopRequireDefault ( require ( "./util/logger" ) ) ;
var _rotate = _interopRequireDefault ( require ( "./util/rotate" ) ) ;
var _rgbToColorAttribute = _interopRequireDefault ( require ( "./util/rgbToColorAttribute" ) ) ;
var _toPiecewiseBezier = _interopRequireWildcard ( require ( "./util/toPiecewiseBezier" ) ) ;
var _transformBoundingBoxAndElement = _interopRequireDefault ( require ( "./util/transformBoundingBoxAndElement" ) ) ;
2024-02-09 11:34:23 +01:00
function _getRequireWildcardCache ( nodeInterop ) { if ( typeof WeakMap !== "function" ) return null ; var cacheBabelInterop = new WeakMap ( ) ; var cacheNodeInterop = new WeakMap ( ) ; return ( _getRequireWildcardCache = function _getRequireWildcardCache ( nodeInterop ) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop ; } ) ( nodeInterop ) ; }
function _interopRequireWildcard ( obj , nodeInterop ) { if ( ! nodeInterop && obj && obj . _ _esModule ) { return obj ; } if ( obj === null || _typeof ( obj ) !== "object" && typeof obj !== "function" ) { return { "default" : obj } ; } var cache = _getRequireWildcardCache ( nodeInterop ) ; if ( cache && cache . has ( obj ) ) { return cache . get ( obj ) ; } var newObj = { } ; var hasPropertyDescriptor = Object . defineProperty && Object . getOwnPropertyDescriptor ; for ( var key in obj ) { if ( key !== "default" && Object . prototype . hasOwnProperty . call ( obj , key ) ) { var desc = hasPropertyDescriptor ? Object . getOwnPropertyDescriptor ( obj , key ) : null ; if ( desc && ( desc . get || desc . set ) ) { Object . defineProperty ( newObj , key , desc ) ; } else { newObj [ key ] = obj [ key ] ; } } } newObj [ "default" ] = obj ; if ( cache ) { cache . set ( obj , newObj ) ; } return newObj ; }
2022-11-06 01:33:32 +01:00
function _interopRequireDefault ( obj ) { return obj && obj . _ _esModule ? obj : { "default" : obj } ; }
function _slicedToArray ( arr , i ) { return _arrayWithHoles ( arr ) || _iterableToArrayLimit ( arr , i ) || _unsupportedIterableToArray ( arr , i ) || _nonIterableRest ( ) ; }
function _nonIterableRest ( ) { throw new TypeError ( "Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method." ) ; }
function _unsupportedIterableToArray ( o , minLen ) { if ( ! o ) return ; if ( typeof o === "string" ) return _arrayLikeToArray ( o , minLen ) ; var n = Object . prototype . toString . call ( o ) . slice ( 8 , - 1 ) ; if ( n === "Object" && o . constructor ) n = o . constructor . name ; if ( n === "Map" || n === "Set" ) return Array . from ( o ) ; if ( n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/ . test ( n ) ) return _arrayLikeToArray ( o , minLen ) ; }
2024-02-09 11:34:23 +01:00
function _arrayLikeToArray ( arr , len ) { if ( len == null || len > arr . length ) len = arr . length ; for ( var i = 0 , arr2 = new Array ( len ) ; i < len ; i ++ ) arr2 [ i ] = arr [ i ] ; return arr2 ; }
function _iterableToArrayLimit ( arr , i ) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr [ Symbol . iterator ] || arr [ "@@iterator" ] ; if ( null != _i ) { var _s , _e , _x , _r , _arr = [ ] , _n = ! 0 , _d = ! 1 ; try { if ( _x = ( _i = _i . call ( arr ) ) . next , 0 === i ) { if ( Object ( _i ) !== _i ) return ; _n = ! 1 ; } else for ( ; ! ( _n = ( _s = _x . call ( _i ) ) . done ) && ( _arr . push ( _s . value ) , _arr . length !== i ) ; _n = ! 0 ) ; } catch ( err ) { _d = ! 0 , _e = err ; } finally { try { if ( ! _n && null != _i [ "return" ] && ( _r = _i [ "return" ] ( ) , Object ( _r ) !== _r ) ) return ; } finally { if ( _d ) throw _e ; } } return _arr ; } }
2022-11-06 01:33:32 +01:00
function _arrayWithHoles ( arr ) { if ( Array . isArray ( arr ) ) return arr ; }
var addFlipXIfApplicable = function addFlipXIfApplicable ( entity , _ref ) {
var bbox = _ref . bbox ,
2024-02-09 11:34:23 +01:00
element = _ref . element ;
2022-11-06 01:33:32 +01:00
if ( entity . extrusionZ === - 1 ) {
return {
bbox : new _vecks . Box2 ( ) . expandByPoint ( {
x : - bbox . min . x ,
y : bbox . min . y
} ) . expandByPoint ( {
x : - bbox . max . x ,
y : bbox . max . y
} ) ,
element : "<g transform=\"matrix(-1 0 0 1 0 0)\">\n " . concat ( element , "\n </g>" )
} ;
} else {
return {
bbox : bbox ,
element : element
} ;
}
} ;
2024-02-09 11:34:23 +01:00
2022-11-06 01:33:32 +01:00
/ * *
* Create a < path / > element . Interpolates curved entities .
* /
var polyline = function polyline ( entity ) {
var vertices = ( 0 , _entityToPolyline [ "default" ] ) ( entity ) ;
var bbox = vertices . reduce ( function ( acc , _ref2 ) {
var _ref3 = _slicedToArray ( _ref2 , 2 ) ,
2024-02-09 11:34:23 +01:00
x = _ref3 [ 0 ] ,
y = _ref3 [ 1 ] ;
2022-11-06 01:33:32 +01:00
return acc . expandByPoint ( {
x : x ,
y : y
} ) ;
} , new _vecks . Box2 ( ) ) ;
var d = vertices . reduce ( function ( acc , point , i ) {
acc += i === 0 ? 'M' : 'L' ;
acc += point [ 0 ] + ',' + point [ 1 ] ;
return acc ;
2024-02-09 11:34:23 +01:00
} , '' ) ;
// Empirically it appears that flipping horzontally does not apply to polyline
2022-11-06 01:33:32 +01:00
return ( 0 , _transformBoundingBoxAndElement [ "default" ] ) ( bbox , "<path d=\"" . concat ( d , "\" />" ) , entity . transforms ) ;
} ;
2024-02-09 11:34:23 +01:00
2022-11-06 01:33:32 +01:00
/ * *
* Create a < circle / > element for the CIRCLE entity .
* /
var circle = function circle ( entity ) {
var bbox0 = new _vecks . Box2 ( ) . expandByPoint ( {
x : entity . x + entity . r ,
y : entity . y + entity . r
} ) . expandByPoint ( {
x : entity . x - entity . r ,
y : entity . y - entity . r
} ) ;
var element0 = "<circle cx=\"" . concat ( entity . x , "\" cy=\"" ) . concat ( entity . y , "\" r=\"" ) . concat ( entity . r , "\" />" ) ;
var _addFlipXIfApplicable = addFlipXIfApplicable ( entity , {
2024-02-09 11:34:23 +01:00
bbox : bbox0 ,
element : element0
} ) ,
bbox = _addFlipXIfApplicable . bbox ,
element = _addFlipXIfApplicable . element ;
2022-11-06 01:33:32 +01:00
return ( 0 , _transformBoundingBoxAndElement [ "default" ] ) ( bbox , element , entity . transforms ) ;
} ;
2024-02-09 11:34:23 +01:00
2022-11-06 01:33:32 +01:00
/ * *
* Create a a < path d = "A..." / > or < ellipse / > element for the ARC or ELLIPSE
* DXF entity ( < ellipse / > if start and end point are the same ) .
* /
var ellipseOrArc = function ellipseOrArc ( cx , cy , majorX , majorY , axisRatio , startAngle , endAngle , flipX ) {
var rx = Math . sqrt ( majorX * majorX + majorY * majorY ) ;
var ry = axisRatio * rx ;
var rotationAngle = - Math . atan2 ( - majorY , majorX ) ;
var bbox = bboxEllipseOrArc ( cx , cy , majorX , majorY , axisRatio , startAngle , endAngle , flipX ) ;
if ( Math . abs ( startAngle - endAngle ) < 1e-9 || Math . abs ( startAngle - endAngle + Math . PI * 2 ) < 1e-9 ) {
// Use a native <ellipse> when start and end angles are the same, and
// arc paths with same start and end points don't render (at least on Safari)
var element = "<g transform=\"rotate(" . concat ( rotationAngle / Math . PI * 180 , " " ) . concat ( cx , ", " ) . concat ( cy , ")\">\n <ellipse cx=\"" ) . concat ( cx , "\" cy=\"" ) . concat ( cy , "\" rx=\"" ) . concat ( rx , "\" ry=\"" ) . concat ( ry , "\" />\n </g>" ) ;
return {
bbox : bbox ,
element : element
} ;
} else {
var startOffset = ( 0 , _rotate [ "default" ] ) ( {
x : Math . cos ( startAngle ) * rx ,
y : Math . sin ( startAngle ) * ry
} , rotationAngle ) ;
var startPoint = {
x : cx + startOffset . x ,
y : cy + startOffset . y
} ;
var endOffset = ( 0 , _rotate [ "default" ] ) ( {
x : Math . cos ( endAngle ) * rx ,
y : Math . sin ( endAngle ) * ry
} , rotationAngle ) ;
var endPoint = {
x : cx + endOffset . x ,
y : cy + endOffset . y
} ;
var adjustedEndAngle = endAngle < startAngle ? endAngle + Math . PI * 2 : endAngle ;
var largeArcFlag = adjustedEndAngle - startAngle < Math . PI ? 0 : 1 ;
var d = "M " . concat ( startPoint . x , " " ) . concat ( startPoint . y , " A " ) . concat ( rx , " " ) . concat ( ry , " " ) . concat ( rotationAngle / Math . PI * 180 , " " ) . concat ( largeArcFlag , " 1 " ) . concat ( endPoint . x , " " ) . concat ( endPoint . y ) ;
var _element = "<path d=\"" . concat ( d , "\" />" ) ;
return {
bbox : bbox ,
element : _element
} ;
}
} ;
2024-02-09 11:34:23 +01:00
2022-11-06 01:33:32 +01:00
/ * *
* Compute the bounding box of an elliptical arc , given the DXF entity parameters
* /
var bboxEllipseOrArc = function bboxEllipseOrArc ( cx , cy , majorX , majorY , axisRatio , startAngle , endAngle , flipX ) {
// The bounding box will be defined by the starting point of the ellipse, and ending point,
// and any extrema on the ellipse that are between startAngle and endAngle.
// The extrema are found by setting either the x or y component of the ellipse's
// tangent vector to zero and solving for the angle.
2024-02-09 11:34:23 +01:00
// Ensure start and end angles are > 0 and well-ordered
while ( startAngle < 0 ) startAngle += Math . PI * 2 ;
while ( endAngle <= startAngle ) endAngle += Math . PI * 2 ;
2022-11-06 01:33:32 +01:00
2024-02-09 11:34:23 +01:00
// When rotated, the extrema of the ellipse will be found at these angles
2022-11-06 01:33:32 +01:00
var angles = [ ] ;
if ( Math . abs ( majorX ) < 1e-12 || Math . abs ( majorY ) < 1e-12 ) {
// Special case for majorX or majorY = 0
for ( var i = 0 ; i < 4 ; i ++ ) {
angles . push ( i / 2 * Math . PI ) ;
}
} else {
// reference https://github.com/bjnortier/dxf/issues/47#issuecomment-545915042
angles [ 0 ] = Math . atan ( - majorY * axisRatio / majorX ) - Math . PI ; // Ensure angles < 0
angles [ 1 ] = Math . atan ( majorX * axisRatio / majorY ) - Math . PI ;
angles [ 2 ] = angles [ 0 ] - Math . PI ;
angles [ 3 ] = angles [ 1 ] - Math . PI ;
2024-02-09 11:34:23 +01:00
}
2022-11-06 01:33:32 +01:00
2024-02-09 11:34:23 +01:00
// Remove angles not falling between start and end
2022-11-06 01:33:32 +01:00
for ( var _i2 = 4 ; _i2 >= 0 ; _i2 -- ) {
2024-02-09 11:34:23 +01:00
while ( angles [ _i2 ] < startAngle ) angles [ _i2 ] += Math . PI * 2 ;
2022-11-06 01:33:32 +01:00
if ( angles [ _i2 ] > endAngle ) {
angles . splice ( _i2 , 1 ) ;
}
2024-02-09 11:34:23 +01:00
}
2022-11-06 01:33:32 +01:00
2024-02-09 11:34:23 +01:00
// Also to consider are the starting and ending points:
2022-11-06 01:33:32 +01:00
angles . push ( startAngle ) ;
2024-02-09 11:34:23 +01:00
angles . push ( endAngle ) ;
2022-11-06 01:33:32 +01:00
2024-02-09 11:34:23 +01:00
// Compute points lying on the unit circle at these angles
2022-11-06 01:33:32 +01:00
var pts = angles . map ( function ( a ) {
return {
x : Math . cos ( a ) ,
y : Math . sin ( a )
} ;
2024-02-09 11:34:23 +01:00
} ) ;
2022-11-06 01:33:32 +01:00
2024-02-09 11:34:23 +01:00
// Transformation matrix, formed by the major and minor axes
var M = [ [ majorX , - majorY * axisRatio ] , [ majorY , majorX * axisRatio ] ] ;
2022-11-06 01:33:32 +01:00
2024-02-09 11:34:23 +01:00
// Rotate, scale, and translate points
2022-11-06 01:33:32 +01:00
var rotatedPts = pts . map ( function ( p ) {
return {
x : p . x * M [ 0 ] [ 0 ] + p . y * M [ 0 ] [ 1 ] + cx ,
y : p . x * M [ 1 ] [ 0 ] + p . y * M [ 1 ] [ 1 ] + cy
} ;
2024-02-09 11:34:23 +01:00
} ) ;
2022-11-06 01:33:32 +01:00
2024-02-09 11:34:23 +01:00
// Compute extents of bounding box
2022-11-06 01:33:32 +01:00
var bbox = rotatedPts . reduce ( function ( acc , p ) {
acc . expandByPoint ( p ) ;
return acc ;
} , new _vecks . Box2 ( ) ) ;
return bbox ;
} ;
2024-02-09 11:34:23 +01:00
2022-11-06 01:33:32 +01:00
/ * *
* An ELLIPSE is defined by the major axis , convert to X and Y radius with
* a rotation angle
* /
var ellipse = function ellipse ( entity ) {
var _ellipseOrArc = ellipseOrArc ( entity . x , entity . y , entity . majorX , entity . majorY , entity . axisRatio , entity . startAngle , entity . endAngle ) ,
2024-02-09 11:34:23 +01:00
bbox0 = _ellipseOrArc . bbox ,
element0 = _ellipseOrArc . element ;
2022-11-06 01:33:32 +01:00
var _addFlipXIfApplicable2 = addFlipXIfApplicable ( entity , {
2024-02-09 11:34:23 +01:00
bbox : bbox0 ,
element : element0
} ) ,
bbox = _addFlipXIfApplicable2 . bbox ,
element = _addFlipXIfApplicable2 . element ;
2022-11-06 01:33:32 +01:00
return ( 0 , _transformBoundingBoxAndElement [ "default" ] ) ( bbox , element , entity . transforms ) ;
} ;
2024-02-09 11:34:23 +01:00
2022-11-06 01:33:32 +01:00
/ * *
* An ARC is an ellipse with equal radii
* /
var arc = function arc ( entity ) {
var _ellipseOrArc2 = ellipseOrArc ( entity . x , entity . y , entity . r , 0 , 1 , entity . startAngle , entity . endAngle , entity . extrusionZ === - 1 ) ,
2024-02-09 11:34:23 +01:00
bbox0 = _ellipseOrArc2 . bbox ,
element0 = _ellipseOrArc2 . element ;
2022-11-06 01:33:32 +01:00
var _addFlipXIfApplicable3 = addFlipXIfApplicable ( entity , {
2024-02-09 11:34:23 +01:00
bbox : bbox0 ,
element : element0
} ) ,
bbox = _addFlipXIfApplicable3 . bbox ,
element = _addFlipXIfApplicable3 . element ;
2022-11-06 01:33:32 +01:00
return ( 0 , _transformBoundingBoxAndElement [ "default" ] ) ( bbox , element , entity . transforms ) ;
} ;
var piecewiseToPaths = function piecewiseToPaths ( k , knots , controlPoints ) {
var paths = [ ] ;
var controlPointIndex = 0 ;
var knotIndex = k ;
while ( knotIndex < knots . length - k + 1 ) {
var m = ( 0 , _toPiecewiseBezier . multiplicity ) ( knots , knotIndex ) ;
var cp = controlPoints . slice ( controlPointIndex , controlPointIndex + k ) ;
if ( k === 4 ) {
paths . push ( "<path d=\"M " . concat ( cp [ 0 ] . x , " " ) . concat ( cp [ 0 ] . y , " C " ) . concat ( cp [ 1 ] . x , " " ) . concat ( cp [ 1 ] . y , " " ) . concat ( cp [ 2 ] . x , " " ) . concat ( cp [ 2 ] . y , " " ) . concat ( cp [ 3 ] . x , " " ) . concat ( cp [ 3 ] . y , "\" />" ) ) ;
} else if ( k === 3 ) {
paths . push ( "<path d=\"M " . concat ( cp [ 0 ] . x , " " ) . concat ( cp [ 0 ] . y , " Q " ) . concat ( cp [ 1 ] . x , " " ) . concat ( cp [ 1 ] . y , " " ) . concat ( cp [ 2 ] . x , " " ) . concat ( cp [ 2 ] . y , "\" />" ) ) ;
}
controlPointIndex += m ;
knotIndex += m ;
}
return paths ;
} ;
exports . piecewiseToPaths = piecewiseToPaths ;
var bezier = function bezier ( entity ) {
var bbox = new _vecks . Box2 ( ) ;
entity . controlPoints . forEach ( function ( p ) {
bbox = bbox . expandByPoint ( p ) ;
} ) ;
var k = entity . degree + 1 ;
var piecewise = ( 0 , _toPiecewiseBezier [ "default" ] ) ( k , entity . controlPoints , entity . knots ) ;
var paths = piecewiseToPaths ( k , piecewise . knots , piecewise . controlPoints ) ;
var element = "<g>" . concat ( paths . join ( '' ) , "</g>" ) ;
return ( 0 , _transformBoundingBoxAndElement [ "default" ] ) ( bbox , element , entity . transforms ) ;
} ;
2024-02-09 11:34:23 +01:00
2022-11-06 01:33:32 +01:00
/ * *
* Switcth the appropriate function on entity type . CIRCLE , ARC and ELLIPSE
* produce native SVG elements , the rest produce interpolated polylines .
* /
var entityToBoundsAndElement = function entityToBoundsAndElement ( entity ) {
switch ( entity . type ) {
case 'CIRCLE' :
return circle ( entity ) ;
case 'ELLIPSE' :
return ellipse ( entity ) ;
case 'ARC' :
return arc ( entity ) ;
case 'SPLINE' :
{
2024-02-09 11:34:23 +01:00
var hasWeights = entity . weights && entity . weights . some ( function ( w ) {
return w !== 1 ;
} ) ;
if ( ( entity . degree === 2 || entity . degree === 3 ) && ! hasWeights ) {
2022-11-06 01:33:32 +01:00
try {
return bezier ( entity ) ;
} catch ( err ) {
return polyline ( entity ) ;
}
} else {
return polyline ( entity ) ;
}
}
case 'LINE' :
case 'LWPOLYLINE' :
case 'POLYLINE' :
{
return polyline ( entity ) ;
}
default :
_logger [ "default" ] . warn ( 'entity type not supported in SVG rendering:' , entity . type ) ;
return null ;
}
} ;
var _default = function _default ( parsed ) {
var entities = ( 0 , _denormalise [ "default" ] ) ( parsed ) ;
var _entities$reduce = entities . reduce ( function ( acc , entity , i ) {
2024-02-09 11:34:23 +01:00
var rgb = ( 0 , _getRGBForEntity [ "default" ] ) ( parsed . tables . layers , entity ) ;
var boundsAndElement = entityToBoundsAndElement ( entity ) ;
// Ignore entities like MTEXT that don't produce SVG elements
if ( boundsAndElement ) {
var _bbox = boundsAndElement . bbox ,
element = boundsAndElement . element ;
// Ignore invalid bounding boxes
if ( _bbox . valid ) {
acc . bbox . expandByPoint ( _bbox . min ) ;
acc . bbox . expandByPoint ( _bbox . max ) ;
}
acc . elements . push ( "<g stroke=\"" . concat ( ( 0 , _rgbToColorAttribute [ "default" ] ) ( rgb ) , "\">" ) . concat ( element , "</g>" ) ) ;
2022-11-06 01:33:32 +01:00
}
2024-02-09 11:34:23 +01:00
return acc ;
} , {
bbox : new _vecks . Box2 ( ) ,
elements : [ ]
} ) ,
bbox = _entities$reduce . bbox ,
elements = _entities$reduce . elements ;
2022-11-06 01:33:32 +01:00
var viewBox = bbox . valid ? {
x : bbox . min . x ,
y : - bbox . max . y ,
width : bbox . max . x - bbox . min . x ,
height : bbox . max . y - bbox . min . y
} : {
x : 0 ,
y : 0 ,
width : 0 ,
height : 0
} ;
2024-02-09 11:34:23 +01:00
return "<?xml version=\"1.0\"?>\n<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\"\n preserveAspectRatio=\"xMinYMin meet\"\n viewBox=\"" . concat ( viewBox . x , " " ) . concat ( viewBox . y , " " ) . concat ( viewBox . width , " " ) . concat ( viewBox . height , "\"\n width=\"100%\" height=\"100%\"\n>\n <g stroke=\"#000000\" stroke-width=\"0.1%\" fill=\"none\" transform=\"matrix(1,0,0,-1,0,0)\">\n " ) . concat ( elements . join ( '\n' ) , "\n </g>\n</svg>" ) ;
2022-11-06 01:33:32 +01:00
} ;
exports [ "default" ] = _default ;