Reading .shp Files
To write a program to open shape editor (.shp) files, you need to be able to read a binary file, process the information and render the vector graphics.
For users of Visual Basic and FreeBASIC, a simple source file with these capabilities is provided.
VB6 Version: modMinimalShapeAPI.bas (19.7 KB)
VB.NET Version: modMinimalShapeAPI.vb (16.4 KB)
FreeBASIC Version: fbMinimalShapeAPI.bas (19.1 KB)
For C programmers using GCC, it may be possable to build the FreeBASIC version as a static library, and use it in a C program.
http://www.freebasic.net/wiki/wikka.php?wakka=TutUsingLibrariesWithGCC
For example the following code samples will create a program that attempts to open a Shape Editor file named 'ShpFile.shp' from the project folder and draw it on a window.
VB6
Create a 'Standard .EXE' project in VB6, add 'modMinimalShapeAPI.bas' to the project and copy the following code to the form:
Dim SD As BShapeData, SH As BShapeHeader, GDIArray() As GDIShape
Private Sub Form_Load()
LoadShapeFile SD, SH, App.Path & "\ShpFile.shp"
ComputeGDIShapes SD, SH, GDIArray
End Sub
Private Sub Form_Paint()
Dim I As Long
For I = 1 To UBound(GDIArray)
HdcDrawGDIShape Me.hdc, GDIArray(I)
Next I
End Sub
VB.NET
Create a new 'Windows Application' project in VB.NET, add 'modMinimalShapeAPI.vb' to the project and copy the following code to the form class after the designer generated code:
Dim SD As BShapeData, SH As BShapeHeader, GDIArray() As GDIShape
Private Sub Form1_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
LoadShapeFile(SD, SH, "ShpFile.shp")
ComputeGDIShapes(SD, SH, GDIArray)
End Sub
Private Sub Form1_Paint(ByVal eventSender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
Dim I As Integer
For I = 1 To UBound(GDIArray)
GraphicsDrawGDIShape(e.Graphics, GDIArray(I))
Next I
End Sub
FreeBASIC
Create a .bas file containing the following code, place fbMinimalShapeAPI.bas in the same folder and make sure you have the runtime files for the cairo vector graphics library.
#Include Once "cairo/cairo.bi"
#Include Once "fbMinimalShapeAPI.bas"
Dim SD As BShapeData, SH As BShapeHeader, DrawArray() As DrawShape
Dim ErrStr As String, cairo_surface As cairo_surface_t Ptr, cr As cairo_t Ptr
'Load a shape file and obtain a drawable representation of it
ErrStr = LoadShapeFile(SD, SH, "ShpFile.shp")
ComputeDrawShapes(SD, SH, DrawArray())
'Obtain a blank white cairo surface on which to draw
ScreenRes SH.ScreenWidth, SH.ScreenHeight, 32
ScreenLock
cairo_surface = cairo_image_surface_create_for_data(ScreenPtr, _
CAIRO_FORMAT_ARGB32, SH.ScreenWidth, _
SH.ScreenHeight, SH.ScreenWidth*Len(Integer))
cr = cairo_create(cairo_surface)
cairo_set_source_rgba(cr, 1, 1, 1, 1)
cairo_paint(cr)
'Draw all the objects in the Shape Editor file
Dim I As Integer
For I = 1 To UBound(DrawArray)
CairoDrawShape(cr, DrawArray(I))
Next I
'Free resources and pause the program
cairo_destroy(cr)
ScreenUnLock
Sleep
Internal Representation of Shapes
As can be seen inside the ShapeAPI file, the basic representation in Shape Editor is Shapes (BShape) composed of Curves (CurvePoints) composed of Points (DoublePoint). In every shape file their is an array for each of these, as seen in the BShapeData structure. These 3 arrays do not use the element at index 0, thus they are defined empty when when their upper bound index (UBound) is 0.
Public Type DoublePoint
X As Double
Y As Double
End Type
Public Type CurvePoints
InplPt() As Long 'lpPoint
NextTanContCurve As Long 'lpCurve
PrevTanContCurve As Long 'lpCurve
End Type
Public Type BShape
Seg() As Long 'lpCurve
Color As Long
CurveThickness As Long
LineColor As Long
Closed As Boolean
ShadeShape As Long 'lpShape
End Type
Public Type BShapeData
PointArray() As DoublePoint
CurveArray() As CurvePoints
ShapeArray() As BShape
End Type
Every Shape in the ShapeArray has an array of indices into the CurveArray, specifying which curves belong to that Shape. Every Shape must have at least one Curve. Every Curve has an array of indicies into the PointArray specifying which points compose that particular curve. Every Curve must have at least 2 points, additionally Curves store indices to adjacent curves with which they are tangent continuous. The convention for adjacent curve indicies is that they are positive if they are in conventional order, ie Curve->Next->Prev = Curve. However, if they are in reversed order, then the indices are negative the correct value to indicate this, ex: Curve->Next->Next = Curve.
Shape Edit Main