参照nicholl-lee-nicholl的原始论文而成,版权归nicholl-lee-nicholl所有. void leftcolumn(float*, float*, float*, float*, float, float, float, float, bool*); void centercolumn(float*, float*, float*, float*, float, float, float, float, bool*); void topleftcorner(float*, float*, float*, float*, float, float, float, float, bool*); void inside(float*, float*, float*, float*, float, float, float, float, bool*); void p2topleft(float*, float*, float*, float*, float, float, float, float, bool*); void leftedge(float*, float*, float*, float*, float, float, float, float, bool*); void leftbottomregion(float*, float*, float*, float*, float, float, float, float, bool*, float, float, float); void p2bottom(float*, float*, float*, float*, float, float, float, float, bool*, float, float); void nlnclip(float* x1, float *y1, float *x2, float *y2, float left, float right, float bottom, float top, bool* visible) { if (*x1 < left) leftcolumn(x1, y1, x2, y2, left, right, bottom, top, visible); else if (*x1 > right) { rotate180c(x1, y1); rotate180c(x2, y2); leftcolumn(x1, y1, x2, y2, -right, -left, -top, -bottom, visible); rotate180c(x1, y1); rotate180c(x2, y2); } else centercolumn(x1, y1, x2, y2, left, right, bottom, top, visible); } void leftcolumn(float* x1, float* y1, float* x2, float* y2, float left, float right, float bottom, float top, bool* visible) { if (*x2 < left) *visible = false; else if (*y1 > top) topleftcorner(x1, y1, x2, y2, left, right, bottom, top, visible); else if (*y1 < bottom) { reflectxaxis(x1, y1); reflectxaxis(x2, y2); topleftcorner(x1, y1, x2, y2, left, right, -top, -bottom, visible); reflectxaxis(x1, y1); reflectxaxis(x2, y2); } else leftedge(x1, y1, x2, y2, left, right, bottom, top, visible); } void topleftcorner(float* x1, float* y1, float* x2, float* y2, float left, float right, float bottom, float top, bool* visible) { float leftproduct, topproduct; float relx, rely; if (*y2 > top) *visible = false; else { relx = *x2 - *x1; rely = *y2 - *y1; leftproduct = (left - *x1) * rely; topproduct = (top - *y1) * relx; if (topproduct > leftproduct) leftbottomregion(x1, y1, x2, y2, left, right, bottom, top, visible, relx, rely, leftproduct); else { reflectxminusy(x1, y1); reflectxminusy(x2, y2); leftbottomregion(x1, y1, x2, y2, -top, -bottom, -right, -left, visible, -rely, -relx, topproduct); reflectxminusy(x1, y1); reflectxminusy(x2, y2); } } } void leftbottomregion(float* x1, float* y1, float* x2, float* y2, float left, float right, float bottom, float top, bool* visible, float relx, float rely, float leftproduct) { float slope; float bottomproduct, rightproduct; if (*y2 > bottom) { slope = rely / relx; if (*x2 > right) { *y2 = (right - *x1) * slope + *y1; *x2 = right; } *y1 = (left - *x1) * slope + *y1; *x1 = left; *visible = true; } else { bottomproduct = (bottom - *y1) * relx; if (bottomproduct > leftproduct) *visible = false; else { rightproduct = (right - *x1) * rely; if (bottomproduct > rightproduct) { slope = rely / relx; *y1 = (left - *x1) * slope + *y1; *x1 = left; *x2 = (bottom - *y1) / slope + *x1; *y2 = bottom; *visible = true; } else { slope = rely / relx; *y1 = (left - *x1) * slope + *y1; *x1 = left; *y2 = (right - *x1) * slope + *y1; *x2 = right; *visible = true; } } } } void leftedge(float* x1, float* y1, float* x2, float* y2, float left, float right, float bottom, float top, bool* visible) { float slope; float relx, rely; relx = *x2 - *x1; rely = *y2 - *y1; if (*x2 < left) *visible = false; else if (*y2 < bottom) p2bottom(x1, y1, x2, y2, left, right, bottom, top, visible, relx, rely); else if (*y2 > top) { reflectxaxis(x1, y1); reflectxaxis(x2, y2); p2bottom(x1, y1, x2, y2, left, right, -top, -bottom, visible, relx, -rely); reflectxaxis(x1, y1); reflectxaxis(x2, y2); } else { slope = rely / relx; if (*x2 > right) { *y2 = (right - *x1) * slope + *y1; *x2 = right; } *y1 = (left - *x1) * slope + *y1; *x1 = left; *visible = true; } } void p2bottom(float* x1, float* y1, float* x2, float* y2, float left, float right, float bottom, float top, bool* visible, float relx, float rely) { float leftproduct, bottomproduct, rightproduct; float slope; leftproduct = (left - *x1) * rely; bottomproduct = (bottom - *y1) * relx; if (bottomproduct > leftproduct) *visible = false; else { rightproduct = (right - *x1) * rely; if (bottomproduct > rightproduct) { slope = rely / relx; *y1 = (left - *x1) * slope + *y1; *x1 = left; *x2 = (bottom - *y1) / slope + *x1; *y2 = bottom; *visible = true; } else { slope = rely / relx; *y1 = (left - *x1) * slope + *y1; *x1 = left; *y2 = (right - *x1) * slope + *y1; *x2 = right; *visible = true; } } } void centercolumn(float* x1, float* y1, float* x2, float* y2, float left, float right, float bottom, float top, bool* visible) { if (*y1 > top) { rotate270c(x1, y1); rotate270c(x2, y2); leftedge(x1, y1, x2, y2, -top, -bottom, left, right, visible); rotate90c(x1, y1); rotate90c(x2, y2); } else if (*y1 < bottom) { rotate90c(x1, y1); rotate90c(x2, y2); leftedge(x1, y1, x2, y2, bottom, top, -right, -left, visible); rotate270c(x1, y1); rotate270c(x2, y2); } else inside(x1, y1, x2, y2, left, right, bottom, top, visible); } void inside(float* x1, float* y1, float* x2, float* y2, float left, float right, float bottom, float top, bool* visible) { float relx, rely; if (*x2 < left) { if (*y2 > top) p2topleft(x1, y1, x2, y2, left, right, bottom, top, visible); else if (*y2 < bottom) { reflectxaxis(x1, y1); reflectxaxis(x2, y2); p2topleft(x1, y1, x2, y2, left, right, -top, -bottom, visible); reflectxaxis(x1, y1); reflectxaxis(x2, y2); } else { relx = *x2 - *x1; rely = *y2 - *y1; *y2 = (left - *x1) * rely / relx + *y1; *x2 = left; *visible = true; } } else if (*x2 > right) { if (*y2 > top) { rotate270c(x1, y1); rotate270c(x2, y2); p2topleft(x1, y1, x2, y2, -top, -bottom, left, right, visible); rotate90c(x1, y1); rotate90c(x2, y2); } else if (*y2 < bottom) { rotate180c(x1, y1); rotate180c(x2, y2); p2topleft(x1, y1, x2, y2, -right, -left, -top, -bottom, visible); rotate180c(x1, y1); rotate180c(x2, y2); } else { relx = *x2 - *x1; rely = *y2 - *y1; *y2 = (right - *x1) * rely / relx + *y1; *x2 = right; *visible = true; } } else if (*y2 > top) { relx = *x2 - *x1; rely = *y2 - *y1; *x2 = (top - *y1) * relx / rely + *x1; *y2 = top; *visible = true; } else if (*y2 < bottom) { relx = *x2 - *x1; rely = *y2 - *y1; *x2 = (bottom - *y1) * relx / rely + *x1; *y2 = bottom; *visible = true; } else *visible = true; } void p2topleft(float* x1, float* y1, float* x2, float* y2, float left, float right, float bottom, float top, bool* visible) { float leftproduct, topproduct; float relx, rely; relx = *x2 - *x1; rely = *y2 - *y1; leftproduct = (left - *x1) * rely; topproduct = (top - *y1) * relx; if (leftproduct < topproduct) { *x2 = (top - *y1) * relx / rely + *x1; *y2 = top; *visible = true; } else { *y2 = (left - *x1) * rely / relx + *y1; *x2 = left; *visible = true; } }